Java BufferedWriter缓冲区大小和占用的内存

Java BufferedWriter缓冲区大小和占用的内存,java,bufferedwriter,Java,Bufferedwriter,我使用BufferedWriter在Java中向文件写入文本。但是,我在构造函数中提供了自定义缓冲区大小。问题是,它以块的形式写入文件,大小与我给定的大小无关。例如,如果我将缓冲区大小设为8KB,则文件将以8KB的大小写入一次。但是,当我使用YourKit profiler查看bufferedwriter对象占用的内存时,它实际上是给定缓冲区大小16KB的两倍 我试图查看内部实现以了解为什么会发生这种情况,我看到它正在创建一个具有给定大小的字符数组。当它写入数组时,它会占用两倍的缓冲区大小,因为

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

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

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

BufferedWriter的大小是字符数组的大小

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

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

但我希望存储在char数组中的所有字符在达到缓冲区大小(在我的示例中为16 KB)时都会写入文件

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

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

在Java中将字符流写入输出文件时,根据某种编码方案将字符编码为字节流。例如,这种编码是由OutputStreamWriter类中的内容执行的


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

谢谢Alex。我知道单字符不是单字节。但我希望存储在char数组中的所有字符在达到缓冲区大小(在我的示例中为16 KB)时都写入文件,因为char数组占用16 KB。但为什么没有发生呢?为什么只刷新8KB的文件?请帮助我理解这取决于你的文件编码。Java使用UTF-16作为其内部字符存储,这意味着对于每个字符,它使用2个字节来存储。但是,如果您的字符仅为ASCII且文件编码为UTF-8,则每个字符仅使用文件中的1个字节,因此是结果。同意@Alex。看见您有1个字符的内部内存表示2 bufferedWriter中的字符缓冲区,3字符到字节的转换,它本身可能也使用字节[]的内部缓冲区,并为每个字符生成可变的字节数。这弥补了复杂的内存使用预测。从鸟瞰的角度来看,2到4倍于字符缓冲区大小似乎是合理的。但最终,8个字符可能会将8个字节写入一个文件。或者16岁。或者10…谢谢@Alex。我现在明白了编码是在做恶作剧@Stephen C。现在我有了更好的洞察力
public BufferedOutputStream(OutputStream out, int size) {
    super(out);
    if (size <= 0) {
        throw new IllegalArgumentException("Buffer size <= 0");
    }
    buf = new byte[size];
}