拆分文本文件而不读取它

时间:2011-11-24 11:25:46

标签: java file

是否有任何方法可以在不读取文件的情况下拆分文本文件?

我想以GB的形式处理一个大文本文件,所以我想将文件分成小部分,并在每个文件上应用线程并合并结果。

因为我将阅读它以获取小部件,然后通过读取它来分割文件将没有任何意义,因为我将不得不两次读取相同的文件,这将降低我的性能。

6 个答案:

答案 0 :(得分:2)

如果不阅读文件内容,则无法执行此操作。这是不可能的。

答案 1 :(得分:2)

由于以下原因,我不认为这是可能的:

  1. 如何在没有“阅读”的情况下编写文件?
  2. 您需要阅读文本以了解字符边界的位置(编码不一定是1个字节)。这意味着您无法将文件视为二进制文件。
  3. 是否真的无法逐行阅读并按此处理?这也节省了分割文件将与原始文件一起占用的额外空间。供您参考,只需阅读文本文件:

    public static void loadFileFromInputStream(InputStream in) throws IOException {
      BufferedReader inputStream = new BufferedReader(new InputStreamReader(in));
    
      String record = inputStream.readLine();
      while (record != null) {
        // do something with the record
        // ...
        record = inputStream.readLine();
      }
    }
    

    您一次只能阅读一行...因此文件的大小根本不会影响性能。您也可以随时停止。如果您喜欢冒险,您还可以将线条添加到单独的线程中以加快处理速度。这样,IO可以在您处理数据时继续搅拌。

    祝你好运!如果由于某种原因,您确实找到了解决方案,请在此处发布。谢谢!

答案 2 :(得分:2)

从技术上讲 - 没有阅读文件就无法完成。但是你也不需要将整个文件内容保存在内存中来进行拆分。只需打开一个文件流,然后通过在将一定数量的字节写入一个文件后将输出重定向到另一个文件来写出其他文件。这样,您无需在任何给定时间在内存中保留多个字节的文件数据。但是拥有更大的缓冲区,大约8或16kb将大大提高性能。

答案 3 :(得分:2)

您的线程尝试形成不良。如果必须对文件数据进行重要处理,请考虑遵循线程结构:

1个读者线程(读取文件并提供工作人员)

  • 带有阅读块的队列

1..n工作线程(n取决于你的cpu核心,处理来自读者线程的数据块)

  • 包含已处理块的队列或字典

1个Writer线程(将结果写入某个文件)

也许您可以将Reader / Writer线程合并到一个线程中,因为在同一个物理硬盘上并行化IO没有多大意义。

很明显,你需要在线程之间进行一些同步。特别是对于队列思考信号量

答案 4 :(得分:1)

有些东西必须读取你的文件才能拆分它(你可能想把它分成线路障碍,可能不是千字节的倍数)。

如果在Linux机器上运行,您可以将拆分委托给外部命令,如csplit。因此,您的Java程序只需运行csplit yourbigfile.txt命令。

答案 5 :(得分:1)

字面意义上没有。要将文件分成较小的文件,您必须读取较大的文件并写入较小的文件。

但是,我想你真的想知道你是否可以让不同的线程同时按顺序读取文件的不同“部分”。答案是你可以做到这一点。只需让每个线程为文件创建自己的RandomAccessFile对象seek到相关位置,然后开始阅读。

(FileInputStream可能也会起作用,但我不认为Java API规范保证使用操作系统级别“搜索”操作来实现skip。 )

有几种可能的并发症:

  • 如果文件是文本,您可能希望每个线程在文件中某行的开头处开始处理。因此,每个线程必须首先查找一行的结尾,并确保它读到其“部分”中最后一行的末尾。

  • 如果文件使用可变宽度字符编码(例如UTF-8),则需要处理分区边界位于字符中间的情况。