【问题标题】:Resume read of huge text file in Java在 Java 中恢复读取巨大的文本文件
【发布时间】:2015-11-17 18:53:44
【问题描述】:

我正在阅读一个巨大的单词文本文件(每行一个单词),但我必须不时停止它以在第二天继续阅读。现在我正在使用 Apache 的 lineiterator 但它完全是错误的解决方案。我的文件是 7Gb,我不得不在 1Gb 左右中断读取它。为了恢复阅读,我保存了已阅读的行数。这意味着我在 while 循环上有一个 if 语句。 Apache 的 FileUtils 不允许搜索,所以这是我的解决方案。

什么是最好/最快的解决方案?我想使用 RandomAccessfile 找到正确的行并继续阅读,但我不确定我是否可以去正确的地方以及如何保存我最后阅读的正确位置。我可以再读几行,所以精度不是那么重要,但我还没有找到获取指针的方法。我有一个 BufferedReader 来读取文件和一个 RandomAccessFile 来寻找正确的位置,但我不知道如何使用 BufferedReader 定期保存位置。 有什么提示吗?

代码:(注意“SOMETHING”,我应该在其中打印可以在 seekToByte 上使用的值)

try {

        RandomAccessFile rand = new RandomAccessFile(file,"r");
        rand.seek(seekToByte);
        startAtByte = rand.getFilePointer();
        rand.close();

    } catch(IOException e) {
        // do something
    }

    // Do it using the BufferedReader 
    BufferedReader reader = null;
    FileReader freader = null;
    try {
        freader = new FileReader(file);
        reader = new BufferedReader(freader);
        reader.skip(startAtByte);

        long i=0;
        for(String line; (line = reader.readLine()) != null; ) {

            lines.add(line);
            System.out.print(i+" ");
            if (lines.size()>1000) {
                commit(lines);
                System.out.println("");
                lines.clear();
                System.out.println(SOMETHING?);
            }
        }

    } catch(Exception e) {
        // handle this           
    } finally {
        if (reader != null) {
            try {reader.close();} catch(Exception ignore) {}
        }
    }

【问题讨论】:

  • 好的,到目前为止你有代码吗?
  • 您是否在任何地方跟踪指针?例如,您是否记下了您已阅读的行数(最好是BigInteger)?
  • @Coffee bitsofinfo.wordpress.com/2009/04/15/… 这是我在写这篇文章之前阅读的代码。
  • 参考stackoverflow.com/questions/4121678/… 考虑到您已经决定如何存储已处理的行数,以上可能会给出一些指导。
  • @Makoto 我用一个 Long 来存储 FileUtils.lineiterator 的行数,但这没有用。它已经跳了 20 分钟,我的计数器只有 42541917

标签: java readfile


【解决方案1】:

RandomAccessfile 确实是一种方法。使用

long position = file.getFilePointer();

当您停止阅读以保存您在文件中的位置,然后恢复时:

file.seek(position);

在同一个地方继续阅读。

但是,使用RandomAccessfile 时要小心,因为它的readLine 方法不完全支持Unicode。

【讨论】:

    【解决方案2】:

    您能否以某种方式使用预先确定的偏移量,例如将文件分成四部分 (offset0, offset1) (offset1, offset2)..etc,并使用 RecursiveAction (ForkJoin API) 来利用并行性。

    【讨论】:

    • 下次我肯定会拆分源文件,但我不想现在这样做,因为我已经完成了 4 个小时的处理。
    • 好吧,我最近没有做太多 Java,但如果我在 C/C++ 中做这件事,我通常会有一个占位符来代表你停止的行号,比如你读 5000000 (5百万行),如果可以的话,您甚至可以将其作为第一件事保存在文件中,因此下一次,您只需读取文件的第一个字节即可知道可以从哪里获取。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-30
    相关资源
    最近更新 更多