【问题标题】:Does java.io.FileWriter buffer bytes before writing to the output streamjava.io.FileWriter 在写入输出流之前是否缓冲字节
【发布时间】:2014-06-18 22:48:14
【问题描述】:

根据 java 文档,

一般来说,Writer 会立即将其输出发送到底层 字符或字节流。除非需要立即输出,否则它是 建议在其 write() 的任何 Writer 周围包装一个 BufferedWriter 操作可能成本很高,例如 FileWriters 和 OutputStreamWriters。 例如,

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));

会将 PrintWriter 的输出缓冲到文件中。无需缓冲, 每次调用 print() 方法都会导致字符 转换成字节,然后立即写入 文件,这可能非常低效。

但是下面的代码看起来好像 FileWriter 在刷新到输出流之前也会缓冲字节。

 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;


 public class TestFileWriter {
 /**
 * @param args
 * @throws IOException 
 */
public static void main(String[] args) throws IOException {
    FileWriter fileWriter= new FileWriter("test.txt");
    File file=new File("test.txt");
    for (int i=0; i<1000; i++) {
        fileWriter.write("a very long string, a very long string, a very long string, a very long string, a very long string\n");
        if(i%50 == 0)
            System.out.print("file size=" +  file.length()+",");

    }
    fileWriter.close();
    System.out.println("file size=" +  file.length());

}

}

输出:-

文件大小=0,文件大小=0,文件大小=8192,文件大小=8192,文件 大小=16384,文件大小=24576,文件大小=24576,文件大小=32768,文件 大小=32768,文件大小=40960,文件大小=49152,文件大小=49152,文件 大小=57344,文件大小=57344,文件大小=65536,文件大小=73728,文件 大小=73728,文件大小=81920,文件大小=81920,文件大小=90112,文件 尺寸=99000

为什么在写入文件时没有将数据写入文件?

【问题讨论】:

  • 所以我知道操作系统正在返回文件大小的缓存信息以防打开文件[file.length()]。但是,当我在将每一行写入文件后断点并打开文件以查看数据是否已写入时,它仍然是空的。
  • +1 个有趣的问题。

标签: java file-io fileoutputstream filewriter bufferedwriter


【解决方案1】:

您对 FileWriter 的假设似乎是正确的。

参考资料:

该类的构造函数假定默认字符编码和默认字节缓冲区大小是可以接受的。

[1]http://docs.oracle.com/javase/6/docs/api/java/io/FileWriter.html

[2]java - Does FileWriter use a buffer? (it acts like it does in my example)

缓冲应用于 Java 的底层 Stream Writing,而不是 FileWriter 级别。

【讨论】:

    【解决方案2】:

    如果你添加

    fileWriter.flush();
    

    您可以看到每行的尺寸都发生了变化。这意味着正在发生缓冲。

    使用调试器,我追踪到 StreamEncoder,它在 Oracle JDK 中没有源代码,但可以在线获得

    http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/nio/cs/StreamEncoder.java

    private static final int DEFAULT_BYTE_BUFFER_SIZE = 8192;
    
    private StreamEncoder(OutputStream out, Object lock, CharsetEncoder enc) {
        // some deleted
        if (ch == null) {
            bb = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE);
        }
    }
    

    如您所见,编码器有自己的缓冲区。

    注意:由于这是一个内部类,它可能会在未来发生变化,并且可能不会在所有平台上都以这种方式运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-09
      • 2016-07-14
      • 1970-01-01
      • 1970-01-01
      • 2018-04-28
      相关资源
      最近更新 更多