BufferedWriter缓冲区大小和占用内存

时间:2017-09-29 07:26:00

标签: java bufferedwriter

我正在使用BufferedWriter将文本写入Java中的文件。但是,我在构造函数中提供自定义缓冲区大小。问题是,它正在以不同大小的块的形式写入文件(例如,如果我将缓冲区大小设置为8KB,则文件写入一次为8KB)。但是,当我查看bufferedwriter对象占用的内存(使用YourKit profiler)时,它实际上是给定缓冲区大小的两倍(在这种情况下为16KB)。

我试着查看内部实现以了解为什么会发生这种情况,我看到它正在创建一个具有给定大小的char数组。当它写入数组时,有意义的是它占用缓冲区大小的两倍,因为每个char占用2个字节。

我的问题是,在这种情况下,BufferedWriter如何管理只写8KB,它在缓冲区中存储16KB。这技术上是否正确?因为每次,即使在缓冲区中有16KB,也只冲洗8KB(一半)。

3 个答案:

答案 0 :(得分:1)

  

但我预计存储在char数组中的所有字符都会在达到缓冲区大小时写入文件(在我给定的例子中为16 KB)。

8K的字符占用16 KB的内存。正确的。

现在我们假设这些字符实际上都在ASCII子集中。

当您使用Java将字符流写入输出文件时,根据某种编码方案将字符编码为字节流。 (例如,此编码由OutputStreamWriter类中的内容执行。)

使用8位字符集/编码方案(如ASCII或Latin-1 ...或UTF-8(!!))对8K字符进行编码时...每个字符编码为1个字节。因此,刷新包含那些 8K字符的缓冲区会产生8K字节写入。

答案 1 :(得分:0)

BufferedWriter的大小是char数组大小。

public BufferedWriter(Writer out, int sz) {
    super(out);
    if (sz <= 0)
        throw new IllegalArgumentException("Buffer size <= 0");
    this.out = out;
    cb = new char[sz];
    nChars = sz;
    nextChar = 0;

    lineSeparator = java.security.AccessController.doPrivileged(
        new sun.security.action.GetPropertyAction("line.separator"));
}

单个字符不等于单个字节。它全部由您的字符编码定义。

因此,要完全按照您的描述执行任务,您必须切换到另一个类:BufferedOutputStream,内部缓冲区按字节数精确计算。

public BufferedOutputStream(OutputStream out, int size) {
    super(out);
    if (size <= 0) {
        throw new IllegalArgumentException("Buffer size <= 0");
    }
    buf = new byte[size];
}

答案 2 :(得分:0)

这取决于用于写入文件的编码:ISO-8859-1将字符存储为单个字节,UTF-8将所有ASCII字符编码为单个字节。