我有一个包含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();
}
将大量数据写入/附加到文件中的最佳方法是什么?
答案 0 :(得分:6)
此处您不需要PrintWriter
。如果你有Writer
种类(例如FileWriter
),你可以简单地在其上调用append(sb)
。而且您不需要flush
,close
暗示刷新。
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)从此文件
创建和OutputStreamWriterOutputStreamWriter 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,性能是否仍然相同?