如何在Java中附加/写入大量数据文件文本

时间:2013-09-10 12:12:34

标签: java file

我有一个包含150k记录的数据库。我想尽快写这个文件。我尝试了很多方法,但看起来都很慢。如何让它更快?

我用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();
}

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

5 个答案:

答案 0 :(得分:6)

此处您不需要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活着而不是刷新每条记录。

答案 1 :(得分:5)

如果您有大量数据,最好不要将它存储到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的功能几乎相同,因此您无需如此更改代码。这种情况的唯一不利之处在于,您的流程将始终涉及数据写入文件,但如果您不在不同的线程中处理数据,则不是问题。

通过这种方式,数据的大小无关紧要

答案 2 :(得分:1)

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

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

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();
    }
}

答案 3 :(得分:0)

您正在打开文件,写一行,然后关闭它。这是开始和结束,花时间在这里。找到一种方法来保持输出文件的打开状态。

答案 4 :(得分:-1)

您是否尝试过Apache IO,性能是否仍然相同?