为什么直接使用print()方法存储数据比将其存储在字符串中然后写入文件更快?

时间:2014-10-24 22:44:10

标签: java file file-writing

让我们考虑这种情况:我正在读取一个文件,然后稍微调整每一行,然后将数据存储在一个新文件中。现在,我尝试了两种方法:

  1. 将数据存储在String中,然后将其写入目标文件,如下所示:

            InputStream ips = new FileInputStream(file);
            InputStreamReader ipsr = new InputStreamReader(ips);
            BufferedReader br = new BufferedReader(ipsr);
    
            PrintWriter desFile = new PrintWriter(targetFilePath);
            String data = "";
            while ((line = br.readLine()) != null) {
                if (line.contains("_Stop_"))
                    continue;
                String[] s = line.split(";");
                String newLine = s[2];
                for (int i = 3; i < s.length; i++) {
                    newLine += "," + s[i];
                }
                data+=newLine+"\n";
            }
            desFile.write(data);
            desFile.close();
            br.close();
    
  2. 在while循环中直接使用printWriter的println()方法:

             while ((line = br.readLine()) != null) {
                if (line.contains("_Stop_"))
                    continue;
                String[] s = line.split(";");
                String newLine = s[2];
                for (int i = 3; i < s.length; i++) {
                    newLine += "," + s[i];
                }
                desFile.println(newLine);
            }
            desFile.close();
            br.close();
    
  3. 第二个过程比第一个过程快。现在,我的问题是在这两个过程中发生的情况如此不同,执行时间差异如此之大?

3 个答案:

答案 0 :(得分:2)

追加到您的字符串:

  1. 为新字符串分配内存
  2. 复制以前复制的所有数据。
  3. 复制新字符串中的数据。
  4. 您对每一行重复此过程,这意味着对于N行输出,您将复制O(N ^ 2)个字节。

    同时,写信给你的PrintWriter:

    1. 将数据复制到缓冲区。
    2. 偶尔冲洗缓冲区。
    3. 意味着对于N行输出,只复制O(N)个字节。

答案 1 :(得分:1)

首先,你通过使用+ =附加来创建大量新的String对象。我认为这肯定会让事情变得缓慢。

尝试使用在循环外部声明的StringBuilder sb追加,然后调用desFile.write(sb.toString());并了解其表现如何。

答案 2 :(得分:1)

首先,这两个进程不会生成相同的数据,因为调用println的数据将在行之间包含行分隔符,而在缓冲区中构建所有数据的行并且不会立刻写下来。

但是性能差异的原因可能是您生成和丢弃的StringStringBuilder对象的大量数量,需要分配的内存来保存内存中的完整文件内容,以及垃圾收集器所花费的时间。

如果您要进行大量的字符串连接,尤其是在循环中,最好在循环之前创建StringBuilder并使用它在循环中累积结果。

但是,如果您要处理大型文件,最好随时编写输出。应用程序的内存要求会降低,而如果在内存中构建整个结果,则所需的内存将等于输出文件的大小。