【问题标题】:How to append/write huge data file text in Java如何在 Java 中追加/写入巨大的数据文件文本
【发布时间】:2013-09-14 03:34:15
【问题描述】:

我有一个包含 15 万条记录的数据库。我想尽快将其写入文件。我尝试了很多方法,但似乎都很慢。如何让这更快?

我以 40k 为单位读取这些记录。所以首先我读了 40k,然后又读了 40k,依此类推。

读取记录后,此过程返回一个包含 40k 行的 StringBuilder。然后我们将这个 StringBuilder 写入一个文件。

private static void write(StringBuilder sb, Boolean append) throws Exception {
    File file = File.createTempFile("foo", ".txt");

    FileWriter writer = new FileWriter(file.getAbsoluteFile(), append);
    PrintWriter out = new PrintWriter(writer);
    try {
        out.print(sb);           
        out.flush();
        writer.flush();
    } finally {
        writer.close();
        out.close();
    }
}

我阅读了另一个示例,但速度同样慢:Fastest way to write huge data in text file Java

我也用 NIO api 试过了:

private static void write(StringBuilder sb, Boolean append)) throws Exception {
    FileChannel rwChannel = new FileOutputStream("textfile.txt", true).getChannel();
    ByteBuffer bb = ByteBuffer.wrap(sb.toString().getBytes("UTF-8"));
    rwChannel.write(bb);
    rwChannel.close();
}

将大量数据写入/追加到文件中的最佳方法是什么?

【问题讨论】:

  • 我相信问题出在out.print(sb)。这会在构建器上强制toString(),而这反过来又涉及复制底层字符数组。如果您需要速度,请尝试使用 char 数组缓冲区和原始字节流进行简单的重写。
  • 是网络通信部分拖慢了你的速度,想办法避免通过网络传输原始数据。或许可以考虑文件压缩以加快传输阶段。

标签: java file


【解决方案1】:

您正在打开文件,写一行,然后关闭它。在这里需要时间的是打开和关闭。想办法让输出文件保持打开状态。

【讨论】:

    【解决方案2】:

    这里不需要PrintWriter。如果你有任何类型的Writer(例如FileWriter),你可以简单地调用append(sb)。而且你不需要flushclose 意味着冲洗。

    private static void write(StringBuilder sb, Boolean append) throws Exception {
      File file = File.createTempFile("foo", ".txt");
    
      try(FileWriter writer = new FileWriter(file.getAbsoluteFile(), append)) {
          writer.append(sb);
      }
    }
    

    在我的系统上,使用Channel 而不是OutputStream,我遇到了小的性能改进:

    private static void write0a(StringBuilder sb, Boolean append) throws Exception {
      File file = File.createTempFile("foo", ".txt");
    
      try(Writer writer = Channels.newWriter(new FileOutputStream(
          file.getAbsoluteFile(), append).getChannel(), "UTF-8")) {
        writer.append(sb);
      }
    }
    

    但是,这些只是轻微的改进。我在这里看不到太多可能性,因为所有代码最终都会调用相同的例程。真正可以提高您的性能的是在调用期间保持 Writer 活着,而不是刷新每条记录。

    【讨论】:

      【解决方案3】:

      你试过 Apache IO,性能还是一样吗?

      【讨论】:

      【解决方案4】:

      如果你的数据量很大,最好不要先存到StringBuilder,然后一次性写入文件。

      这是最好的场景:

      1) 在开始处理数据之前创建 FileInputStream

      FileOutputStream fos = new FileOutputStream("/path/of/your/file");
      

      2) 从此文件创建和 OutputStreamWriter

      OutputStreamWriter w = new OutputStreamWriter(fos, "UTF-8");
      

      3)创建BufferedWriter(提高文件写入性能)

      BufferedWriter bw = new BufferedWriter(w);
      

      4) 将 bw 传递给您的进程函数,然后刷新/关闭

      bw.flush();
      bw.close();
      

      StringBuilder 和 BufferedWriter 的功能几乎相同,所以你不需要对你的代码做太多改动。这种情况的唯一缺点是,您的进程将涉及数据写入文件的所有时间,但如果您不在不同的线程中处理数据,这不是问题。

      这样一来,数据量多大都无所谓了

      【讨论】:

        【解决方案5】:

        您正在使用 FileWriter(或第二个示例中的 FileOutputStream)。这些没有缓冲!所以他们分别写单个字符。字节到磁盘。

        这意味着,您应该将 FileWriter 包装在 BufferedWriter 中(或将 FileOutputSystem 包装在 BufferedOutputSystem 中)。

        private static void write(StringBuilder sb, Boolean append) throws Exception {
            File file = File.createTempFile("foo", ".txt");
            Writer writer = new BufferedWriter(new FileWriter(file.getAbsoluteFile(), append));
            PrintWriter out = new PrintWriter(writer);
            try {
                out.print(sb);           
                out.flush();
                writer.flush();
            } finally {
                writer.close();
                out.close();
            }
        }
        

        【讨论】:

        • 不,来自FileWriter的javadoc:The constructors of this class assume that the default character encoding and the default byte-buffer size are acceptable
        • 哦,是的。你说的对。我想到了 FileOutputStream(并且错误地认为 FileWriter 的行为相同)。嗯...
        猜你喜欢
        • 2011-06-14
        • 2012-04-12
        • 1970-01-01
        • 2016-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-26
        相关资源
        最近更新 更多