我正在使用BufferedWriter将文本写入Java中的文件。但是,我在构造函数中提供自定义缓冲区大小。问题是,它正在以不同大小的块的形式写入文件(例如,如果我将缓冲区大小设置为8KB,则文件写入一次为8KB)。但是,当我查看bufferedwriter对象占用的内存(使用YourKit profiler)时,它实际上是给定缓冲区大小的两倍(在这种情况下为16KB)。
我试着查看内部实现以了解为什么会发生这种情况,我看到它正在创建一个具有给定大小的char数组。当它写入数组时,有意义的是它占用缓冲区大小的两倍,因为每个char占用2个字节。
我的问题是,在这种情况下,BufferedWriter如何管理只写8KB,它在缓冲区中存储16KB。这技术上是否正确?因为每次,即使在缓冲区中有16KB,也只冲洗8KB(一半)。
答案 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字符编码为单个字节。