Java-防止PrintWriter每次都覆盖整个文件

Java-防止PrintWriter每次都覆盖整个文件,java,csv,printwriter,Java,Csv,Printwriter,我有一个模拟程序,需要在执行过程中频繁地将某些结果写入csv文件。我发现printwriter有点问题,因为输出文件越来越大(接近100万行),所以运行程序的速度大大减慢。我怀疑每次从一开始它都会覆盖整个文件,而每次调用它时我只需要在底部附加一行。下面是与编写功能相关的代码 写作功能之一: public void printHubSummary(Hub hub, String filePath) { try { StringBui

我有一个模拟程序,需要在执行过程中频繁地将某些结果写入csv文件。我发现printwriter有点问题,因为输出文件越来越大(接近100万行),所以运行程序的速度大大减慢。我怀疑每次从一开始它都会覆盖整个文件,而每次调用它时我只需要在底部附加一行。下面是与编写功能相关的代码

写作功能之一:

    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});
}