在 java 中写入和附加大文件的最佳方法是什么
What is the best way to write and append a large file in java
我有一个 java 程序,它向网络服务发送一系列 GET 请求并将响应正文存储为文本文件。
我已经实现了以下示例代码(过滤了大部分代码以突出显示相关内容),它附加了文本文件并在 EOF 处作为新行写入。然而,该代码可以完美运行,但随着文件大小的增加,性能会受到影响。
数据总大小将近 4 GB,平均每 1 MB 数据附加约 500 KB。
do
{
//send the GET request & fetch data as string
String resultData = HTTP.GET <uri>;
// buffered writer to create a file
BufferedWriter writer = new BufferedWriter(new FileWriter(path, true));
//write or append the file
writer.write(resultData + "\n");
}
while(resultData.exists());
这些文件每天都会创建并移动到 hdfs 以供 hadoop 使用并作为实时存档。有没有更好的方法来实现这个?
根据这个答案Java difference between FileWriter and BufferedWriter你现在所做的事情效率低下。
您提供的代码不完整。缺少括号,作者没有 close
声明。但是,如果我对每个 resultData
的理解正确,您将打开一个新的缓冲写入器并调用 write once 。这意味着你应该直接使用 FileWriter
,因为你这样做的方式,缓冲区只是一个开销。
如果你想让它循环获取数据并将它们写入单个文件,那么你应该这样做
try( BufferedWriter writer = new BufferedWriter(new FileWriter("PATH_HERE", true)) ) {
String resultData = "";
do {
//send the GET request & fetch data as string
resultData = HTTP.GET <uri>;
//write or append the file
writer.write(resultData + "\n");
} while(resultData != null && !resultData.isEmpty());
} catch(Exception e) {
e.printStackTrace();
}
上面使用了try with resources,它会在退出try
块后处理关闭writer。这在 java 7 中可用。
1) 您每次都打开一个新的 writer
,而没有关闭之前的 writer
对象。
2)不要每次写操作都打开文件,而是在循环前打开,循环后关闭。
BufferedWriter writer = new BufferedWriter(new FileWriter(path, true));
do{
String resultData = HTTP.GET <uri>;
writer.write(resultData + "\n");
}while(resultData.exists());
writer.close();
3) BufferedWriter
的默认缓冲大小是 8192 个字符,因为你有 4 GB 的数据,我会增加缓冲区大小,以提高性能但同时确保你的 JVM 有足够的保存数据的内存。
BufferedWriter writer = new BufferedWriter(new FileWriter(path, true), 8192 * 4);
do{
String resultData = HTTP.GET <uri>;
writer.write(resultData + "\n");
}while(resultData.exists());
writer.close();
4) 由于您正在进行 GET 网络服务调用,因此性能还取决于 webservice
的 response
时间。
我有一个 java 程序,它向网络服务发送一系列 GET 请求并将响应正文存储为文本文件。
我已经实现了以下示例代码(过滤了大部分代码以突出显示相关内容),它附加了文本文件并在 EOF 处作为新行写入。然而,该代码可以完美运行,但随着文件大小的增加,性能会受到影响。
数据总大小将近 4 GB,平均每 1 MB 数据附加约 500 KB。
do
{
//send the GET request & fetch data as string
String resultData = HTTP.GET <uri>;
// buffered writer to create a file
BufferedWriter writer = new BufferedWriter(new FileWriter(path, true));
//write or append the file
writer.write(resultData + "\n");
}
while(resultData.exists());
这些文件每天都会创建并移动到 hdfs 以供 hadoop 使用并作为实时存档。有没有更好的方法来实现这个?
根据这个答案Java difference between FileWriter and BufferedWriter你现在所做的事情效率低下。
您提供的代码不完整。缺少括号,作者没有 close
声明。但是,如果我对每个 resultData
的理解正确,您将打开一个新的缓冲写入器并调用 write once 。这意味着你应该直接使用 FileWriter
,因为你这样做的方式,缓冲区只是一个开销。
如果你想让它循环获取数据并将它们写入单个文件,那么你应该这样做
try( BufferedWriter writer = new BufferedWriter(new FileWriter("PATH_HERE", true)) ) {
String resultData = "";
do {
//send the GET request & fetch data as string
resultData = HTTP.GET <uri>;
//write or append the file
writer.write(resultData + "\n");
} while(resultData != null && !resultData.isEmpty());
} catch(Exception e) {
e.printStackTrace();
}
上面使用了try with resources,它会在退出try
块后处理关闭writer。这在 java 7 中可用。
1) 您每次都打开一个新的 writer
,而没有关闭之前的 writer
对象。
2)不要每次写操作都打开文件,而是在循环前打开,循环后关闭。
BufferedWriter writer = new BufferedWriter(new FileWriter(path, true));
do{
String resultData = HTTP.GET <uri>;
writer.write(resultData + "\n");
}while(resultData.exists());
writer.close();
3) BufferedWriter
的默认缓冲大小是 8192 个字符,因为你有 4 GB 的数据,我会增加缓冲区大小,以提高性能但同时确保你的 JVM 有足够的保存数据的内存。
BufferedWriter writer = new BufferedWriter(new FileWriter(path, true), 8192 * 4);
do{
String resultData = HTTP.GET <uri>;
writer.write(resultData + "\n");
}while(resultData.exists());
writer.close();
4) 由于您正在进行 GET 网络服务调用,因此性能还取决于 webservice
的 response
时间。