有没有比创建满足以下条件的流式文件读取器类更好的[预先存在的可选 Java 1.6] 解决方案?
- 给定一个任意大的 ASCII 文件,其中每一行都以
\n
结尾
- 对于某些方法
readLine()
的每次调用,从文件中随机读取一行 - 并且在文件句柄的生命周期内,对
readLine()
的调用不应返回同一行两次
更新:
- 最终必须阅读所有行
上下文:文件的内容是从 Unix shell 命令创建的,以获取给定目录中包含的所有路径的目录列表;有数百万到十亿个文件(在目标文件中产生数百万到十亿行)。如果有某种方法可以在创建期间将路径随机分配到文件中,这也是一个可接受的解决方案。
最佳答案
为了避免读取整个文件,这在您的情况下可能是不可能的,您可能需要使用 RandomAccessFile
而不是标准的 java FileInputStream
。使用 RandomAccessFile
,您可以使用 seek(long position)
方法跳到文件中的任意位置并从那里开始读取。代码看起来像这样。
RandomAccessFile raf = new RandomAccessFile("path-to-file","rw");
HashMap<Integer,String> sampledLines = new HashMap<Integer,String>();
for(int i = 0; i < numberOfRandomSamples; i++)
{
//seek to a random point in the file
raf.seek((long)(Math.random()*raf.length()));
//skip from the random location to the beginning of the next line
int nextByte = raf.read();
while(((char)nextByte) != '\n')
{
if(nextByte == -1) raf.seek(0);//wrap around to the beginning of the file if you reach the end
nextByte = raf.read();
}
//read the line into a buffer
StringBuffer lineBuffer = new StringBuffer();
nextByte = raf.read();
while(nextByte != -1 && (((char)nextByte) != '\n'))
lineBuffer.append((char)nextByte);
//ensure uniqueness
String line = lineBuffer.toString();
if(sampledLines.get(line.hashCode()) != null)
i--;
else
sampledLines.put(line.hashCode(),line);
}
在这里,sampledLines
应该在末尾保留您随机选择的行。您可能还需要检查您是否没有随机跳到文件末尾,以避免在这种情况下出现错误。
编辑:我让它换行到文件的开头,以防你到达结尾。这是一个非常简单的检查。
编辑 2: 我使用 HashMap
验证行的唯一性。
关于Java:具有状态的 ASCII 随机行文件访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14338350/