Java:使用状态的ASCII随机行文件访问

cfe*_*uke 4 java io

有没有比创建符合以下条件的流式文件阅读器类更好的[预先存在的可选Java 1.6]解决方案?

  • 给定一个任意大小的ASCII文件,其中每行以a结尾 \n
  • 对于某些方法的每次调用,readLine()从文件中读取一个随机行
  • 并且对于文件句柄的生命,没有调用readLine()应该返回相同的行两次

更新:

  • 最终必须读取所有行

上下文:文件的内容是从Unix shell命令创建的,以获取给定目录中包含的所有路径的目录列表; 有数百万到十亿个文件(在目标文件中产生数百万到十亿行).如果有一些方法可以在创建时间内将路径随机分配到文件中,这也是一种可接受的解决方案.

S E*_*S E 5

为了避免读取整个文件(在您的情况下可能无法读取),您可能希望使用RandomAccessFile标准java而不是标准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);
}
Run Code Online (Sandbox Code Playgroud)

在这里,sampledLines应该在最后保留随机选择的行.您可能需要检查是否也没有随机跳过文件的末尾以避免在这种情况下出错.

编辑:我把它包装到文件的开头,以防你到达最后.这是一个非常简单的检查.

编辑2:我通过使用a来验证行的唯一性HashMap.