BufferedWriter缓冲区大小和占用内存

BufferedWriter buffer size and occupied memory

我正在使用 BufferedWriter 将文本写入 Java 中的文件。但是,我在构造函数中提供了自定义缓冲区大小。问题是,无论我给出的大小是多少,它都会以块的形式写入文件(例如,如果我将缓冲区大小设置为 8KB,则文件一次写入 8KB)。但是,当我查看 bufferedwriter 对象占用的内存时(使用 YourKit 分析器),它实际上是给定缓冲区大小的两倍(在本例中为 16KB)。

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

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

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

单个字符不等于单个字节。都是由你的字符编码定义的。

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

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

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

But I expected all the chars stored in the char array to be written to the file when it reaches the buffer size (which would be 16 KB in my given example).

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

现在假设字符实际上都在 ASCII 子集中。

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

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