Java-防止PrintWriter每次都覆盖整个文件
我有一个模拟程序,需要在执行过程中频繁地将某些结果写入csv文件。我发现printwriter有点问题,因为输出文件越来越大(接近100万行),所以运行程序的速度大大减慢。我怀疑每次从一开始它都会覆盖整个文件,而每次调用它时我只需要在底部附加一行。下面是与编写功能相关的代码 写作功能之一:Java-防止PrintWriter每次都覆盖整个文件,java,csv,printwriter,Java,Csv,Printwriter,我有一个模拟程序,需要在执行过程中频繁地将某些结果写入csv文件。我发现printwriter有点问题,因为输出文件越来越大(接近100万行),所以运行程序的速度大大减慢。我怀疑每次从一开始它都会覆盖整个文件,而每次调用它时我只需要在底部附加一行。下面是与编写功能相关的代码 写作功能之一: public void printHubSummary(Hub hub, String filePath) { try { StringBui
public void printHubSummary(Hub hub, String filePath) {
try {
StringBuilder sb = new StringBuilder();
String h = hub.getHub_code();
String date = Integer.toString(hub.getGs().getDate());
String time = hub.getGs().getHHMMFromMinute(hub.getGs().getClock());
String wgt = Double.toString(hub.getIb_wgt());
sb.append(h+","+date+","+time+","+wgt);
// System.out.println("truck print line: " + sb);
FileWriter.writeFile(sb.toString(),filePath);
}
catch (Exception e) {
System.out.println("Something wrong when outputing truck summary file!");
e.printStackTrace();
}
}
文件编写器代码:(应该在问题所在的位置!)
关于代码修改的更新。我已经冻结了重复对整个文件进行过度加载的操作。它似乎解决了问题,但有时写作速度也慢了下来。这是书写超大文件的最佳安排吗?还可以做哪些其他修改来提高效率
public static boolean writeFile1(String newStr, String filename) throws IOException {
boolean flag = false;
String filein = newStr + "\r\n";
String temp = "";
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
FileOutputStream fos = null;
PrintWriter pw = null;
try {
File file = new File(filename);
fis = new FileInputStream(file);
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);
StringBuffer buf = new StringBuffer();
// for (int j = 1; (temp = br.readLine()) != null; j++) {
// buf = buf.append(temp);
// buf = buf.append(System.getProperty("line.separator"));
// }
// if (buf.length() > 0 && buf.charAt(0) == '\uFEFF') {
// buf.deleteCharAt(0);
// }
buf.append(filein);
fos = new FileOutputStream(file,true);
byte[] unicode = {(byte)0xEF, (byte)0xBB, (byte)0xBF};
fos.write(unicode);
pw = new PrintWriter(fos);
pw.write(buf.toString().toCharArray());
pw.flush();
flag = true;
} catch (IOException e1) {
throw e1;
} finally {
if (pw != null) {
pw.close();
}
if (fos != null) {
fos.close();
}
if (br != null) {
br.close();
}
if (isr != null) {
isr.close();
}
if (fis != null) {
fis.close();
}
}
return flag;
}
为
FileOutputStream
构造函数提供第二个参数,以指定是否使用附加模式,该模式将添加到文件末尾,而不是覆盖它
fos = new FileOutputStream(file, true);
或者,您可以在append模式下创建一个静态PrintWriter,这可能会更快,因为它减少了垃圾收集。使用更丰富的Files/Path/Java NIO2:下面的代码至少需要Java 7
Path path = Paths.get(filename);
try (BufferedWriter bw = Files.newBufferedWriter(
path, StandardCharsets.UTF_8, StandardOpenOption.APPEND, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
bw.append(filein);
bw.newLine();
}
这里的提示是StandardOpenOption
在编写Unicode部分(并修复标准字符集.UTF_8
)之前,您可能需要执行一些额外的代码:
另外,尽量不要在本地方法中使用
StringBuffer
,请使用StringBuilder
:大多数时候不需要同步。我不确定是否理解。每次写新行时,是否读取整个文件?然后再次写入整个文件?只需保持您的一个printWriter处于活动状态,不要在调用函数时创建新的printWriter,反复使用该printWriter即可。或者在“附加”模式下打开文件,只写新行。我怀疑是这样,这可能是原因。@luk2302您能建议对代码进行具体修改吗?我建议阅读一些文档。我看不出有任何理由将整个文件读入字符串,然后再将其写出来。如果这是一个长时间运行的操作,随着丢失数据的可能性增加,我会小心保持文件的打开状态。添加“true”会变得更慢,为什么?@Jack我不确定。但是它能工作吗?它变得更慢了。差点卡住@Jack进行此修改后,不要读取整个文件并将其写回,因为不再需要这样做。只写实际需要添加的部分,即只需在中写入文件。请查看编辑中的“我的更新”。现在它以更快的速度运行。但这是书写超大文件的最佳安排吗?还可以做哪些其他修改来提高效率?
Path path = Paths.get(filename);
try (BufferedWriter bw = Files.newBufferedWriter(
path, StandardCharsets.UTF_8, StandardOpenOption.APPEND, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
bw.append(filein);
bw.newLine();
}
if (Files.notExists(path)) {
Files.write(path, new byte[] {(byte)0xEF, (byte)0xBB, (byte)0xBF});
}