我正在使用BufferedWriter在Java中写下文本。但是,我在构造函数中提供自定义缓冲尺寸。事实是,它是在我给出的大小的块中写入文件(例如,如果我将缓冲区大小作为8KB,则文件是为8KB编写一次)。但是,当我查看被缓冲作者对象占据的内存(使用YourKit Profiler)时,它实际上是给定的缓冲区大小的两倍(在这种情况下为16KB)。
我试图查看内部实现,以了解为什么会发生这种情况,我发现它正在创建一个带有给定尺寸的字符数组。当它写入数组时,它占据了两倍的缓冲尺寸,因为每个炭都占据了2个字节。
我的问题是,在这种情况下,如何仅写8kb,在这种情况下,在缓冲区中存储16KB。这在技术上是正确的吗?因为每次,即使在缓冲区中有16kb,它也只会冲洗8kb(一半)。
,但我希望将所有存储在字符阵列中的字符达到缓冲区大小时都写在文件中(在我给定的示例中为16 kb)。
8k的chars占据16 kb的内存。正确。
现在,假设字符实际上都在ASCII子集中。
当您将字符流写入Java中的输出文件时,根据某些编码方案将字符编码为字节流。(例如,OutputStreamWriter
类中的内容执行此编码。)
当您使用8位字符集/编码方案(例如ASCII或Latin-1 ...或utf-8(!!))编码那些8k字符时...每个字符均编码为1个字节。因此,将包含的缓冲区刷新这些 8k字符会生成8k字节写。
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"));
}
单个char不等于一个字节。所有这些都由您的角色编码定义。
因此,要准确地执行任务,如您所描述的那样,您必须切换到另一个类: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字符编码为单个字节。