Java:具有状态的 ASCII 随机行文件访问

标签 java io

有没有比创建满足以下条件的流式文件读取器类更好的[预先存在的可选 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/

相关文章:

graphics - 如何直接写到屏幕上?

haskell - 如何构建 IO 的 Haskell 代码?

java - Android - 定时器类

java.io.NotSerializableException 数据类型

java - 强制继承链的每个类覆盖抽象方法

c - 读(): Invalid arguments

c - 无法在 Windows 上写入文件

java - 如何在 Java 中打开带有 anchor 的 URL?

java - findViewById(R.id.progressbar) 和静态 hell :

haskell - Haskell : abort writeFile on error