我有一个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();
}
}
Run Code Online (Sandbox Code Playgroud)
我读了这个其他的例子,但它同样很慢:在文本文件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();
}
Run Code Online (Sandbox Code Playgroud)
将大量数据写入/附加到文件中的最佳方法是哪种?
你不需要PrintWriter这里.如果您有任何类型Writer(例如a 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);
}
}
Run Code Online (Sandbox Code Playgroud)
在我的系统上,我遇到了一个小的性能改进,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);
}
}
Run Code Online (Sandbox Code Playgroud)
然而,这些只是轻微的改进.我没有看到很多可能性,因为所有代码最终调用相同的例程.能够真正提高性能的是在调用期间保持Writer活着,而不是刷新每条记录.
如果您有大量数据,最好不要将它存储到StringBuilder,然后立即将其写入文件.
这是最好的方案:
1)在开始处理数据之前创建FileInputStream
FileOutputStream fos = new FileOutputStream("/path/of/your/file");
Run Code Online (Sandbox Code Playgroud)
2)从该文件创建和OutputStreamWriter
OutputStreamWriter w = new OutputStreamWriter(fos, "UTF-8");
Run Code Online (Sandbox Code Playgroud)
3)创建BufferedWriter(提高文件写入性能)
BufferedWriter bw = new BufferedWriter(w);
Run Code Online (Sandbox Code Playgroud)
4)将bw传递给过程函数,然后冲洗/关闭
bw.flush();
bw.close();
Run Code Online (Sandbox Code Playgroud)
StringBuilder和BufferedWriter的功能几乎相同,因此您不需要更改代码.这种情况的唯一不利之处在于,您的流程将涉及数据写入文件的所有时间,但如果您不在不同的线程中处理数据,则不是问题.
通过这种方式,数据的大小并不重要