使用Java Nio将String写入文件的最佳方法
我需要使用java nio将巨大的字符串写入(附加)到平面文件。编码为ISO-8859-1。
目前,我们正在编写如下图所示。有没有 方法可以做到这一点?
public void writeToFile(Long limit) throws IOException{ String fileName = "/xyz/test.txt";
File file = new File(fileName);
FileOutputStream fileOutputStream = new FileOutputStream(file, true);
FileChannel fileChannel = fileOutputStream.getChannel();
ByteBuffer byteBuffer = null;
String messageToWrite = null;
for(int i=1; i<limit; i++){
//messageToWrite = get String Data From database
byteBuffer = ByteBuffer.wrap(messageToWrite.getBytes(Charset.forName("ISO-8859-1")));
fileChannel.write(byteBuffer);
}
fileChannel.close();
}
编辑:尝试了两个选项。以下是结果。
@Testpublic void testWritingStringToFile() {
DiagnosticLogControlManagerImpl diagnosticLogControlManagerImpl = new DiagnosticLogControlManagerImpl();
try {
File file = diagnosticLogControlManagerImpl.createFile();
long startTime = System.currentTimeMillis();
writeToFileNIOWay(file);
//writeToFileIOWay(file);
long endTime = System.currentTimeMillis();
System.out.println("Total Time is " + (endTime - startTime));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
*
* @param limit
* Long
* @throws IOException
* IOException
*/
public void writeToFileNIOWay(File file) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream(file, true);
FileChannel fileChannel = fileOutputStream.getChannel();
ByteBuffer byteBuffer = null;
String messageToWrite = null;
for (int i = 1; i < 1000000; i++) {
messageToWrite = "This is a test üüüüüüööööö";
byteBuffer = ByteBuffer.wrap(messageToWrite.getBytes(Charset
.forName("ISO-8859-1")));
fileChannel.write(byteBuffer);
}
}
/**
*
* @param limit
* Long
* @throws IOException
* IOException
*/
public void writeToFileIOWay(File file) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream(file, true);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
fileOutputStream, 128 * 100);
String messageToWrite = null;
for (int i = 1; i < 1000000; i++) {
messageToWrite = "This is a test üüüüüüööööö";
bufferedOutputStream.write(messageToWrite.getBytes(Charset
.forName("ISO-8859-1")));
}
bufferedOutputStream.flush();
fileOutputStream.close();
}
private File createFile() throws IOException {
File file = new File(FILE_PATH + "test_sixth_one.txt");
file.createNewFile();
return file;
}
回答:
我认为,如果不对软件进行基准测试,您将无法得到严格的答案。在适当的条件下,NIO可能会大大加快应用程序的速度,但同时也会使事情变慢。以下是一些要点:
- 您真的需要琴弦吗?如果您从数据库存储和接收字节,则可以避免字符串分配和编码成本的总和。
- 你真的需要
rewind
和flip
?似乎您正在为每个字符串创建一个新缓冲区,然后将其写入通道。(如果您采用NIO方式,则可以重用缓冲区而不是包装/丢弃的基准策略,我认为它们会做得更好)。 - 请记住,
wrap
和allocateDirect可能会产生完全不同的缓冲区。两者都要进行基准测试,以权衡取舍。对于直接分配,请确保重用相同的缓冲区,以实现最佳性能。 - 最重要的是:确保将NIO与BufferedOutputStream和/或BufferedWritter方法进行比较(也使用大小合适的中间件
byte[]
或char[]
缓冲区)。我见过很多,很多,很多人发现,NIO没有银弹。
如果您喜欢某些前沿技术,请返回IO
Trails以获取一些NIO2:D。
这是有关使用不同策略进行文件复制的有趣基准。我知道这是一个不同的问题,但是我认为大多数事实和作者结论也适用于您的问题。
干杯,
更新1:
由于@EJP提示我直接缓冲区对于解决此问题并不有效,因此我自己对其进行了基准测试,并最终使用内存映射文件开发了一个不错的NIO解决方案。在运行OS X
Lion的Macbook中,这一点可观BufferedOutputStream
。但请记住,这可能是特定于OS /硬件/ VM的:
public void writeToFileNIOWay2(File file) throws IOException { final int numberOfIterations = 1000000;
final String messageToWrite = "This is a test üüüüüüööööö";
final byte[] messageBytes = messageToWrite.
getBytes(Charset.forName("ISO-8859-1"));
final long appendSize = numberOfIterations * messageBytes.length;
final RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.seek(raf.length());
final FileChannel fc = raf.getChannel();
final MappedByteBuffer mbf = fc.map(FileChannel.MapMode.READ_WRITE, fc.
position(), appendSize);
fc.close();
for (int i = 1; i < numberOfIterations; i++) {
mbf.put(messageBytes);
}
}
我承认我通过预先计算要添加的总大小(大约26
MB)而有所作弊。对于某些实际情况,这可能是不可能的。不过,您始终可以为操作使用“足够大的附加大小”,并在以后截断文件。
更新2(2019):
对于任何寻求现代(如Java
11+)解决方案的人,我将遵循@DodgyCodeException的建议并使用java.nio.file.Files.writeString
:
String fileName = "/xyz/test.txt";String messageToWrite = "My long string";
Files.writeString(Paths.get(fileName), messageToWrite, StandardCharsets.ISO_8859_1);
以上是 使用Java Nio将String写入文件的最佳方法 的全部内容, 来源链接: utcz.com/qa/411998.html