提问人:kaka 提问时间:7/27/2023 更新时间:7/28/2023 访问量:150
即使我将缓冲区大小设置为 1,BufferedInputStream 也会读取整个文件一次?
BufferedInputStream reads the entire file once even though I set the buffer size to 1?
问:
我正在运行下面的代码来尝试了解 BufferedInputStream 在 Java 中的工作原理。我将缓冲区大小设置为 1,并期望缓冲区读取文件 465 次,因为这是文件中的字符量。但是,它读取文件一次。我发现更改缓冲区读取文件的次数,您将字节数组更改为 1。在这种情况下,它会读取文件 465 次。我不明白为什么即使我将缓冲区大小设置为 1,缓冲区也会读取文件一次。为什么数组“does”决定缓冲区读取文件的次数?
File f = new File("runs");
if(!f.exists()) {
f.createNewFile();
}
FileInputStream input = new FileInputStream(f);
BufferedInputStream b = new BufferedInputStream(input, 1);
byte[] does = new byte[1000];
int i = b.read(does);
int x = 0;
String tmp;
while(i != -1) {
tmp = new String(does, StandardCharsets.UTF_8);
if(!tmp.equalsIgnoreCase("\n")) {
System.out.print(tmp);
}else {
System.out.println(tmp);
}
x++;
i = b.read(does);
}
System.out.println(x);
}
答:
BufferedInputStream 和 InputStream 中方法的差异。
read()
让我们从输入流中读取单个字节的数据并将其作为值返回,该值将在 2 条件下被阻止,检测到流的末尾或引发异常。
While 为传递的输入流添加缓冲。InputStream.read
int
BufferedInputStream
区别在于以块的形式从底层输入流中读取数据并将其存储在内部缓冲区中,因此当您调用方法时,它会从其缓冲区返回下一个字节,因此区别在于数据调用开销量,其中通过将多个数据请求分组到来自底层输入流的较少调用中来减少它。BufferedInputStream
read()
BufferedInputStream
为什么 BufferedInputStream 即使在指定缓冲区大小时也会读取整个文件?
它实际上不会,即使指定了缓冲区大小,它也不一定会将整个文件读入缓冲区,实际上它会以块或块的形式将数据从文件读入缓冲区,其大小最多是缓冲区的大小,文件被读取的次数取决于文件的大小和使用的缓冲区的大小, 在共享代码段中,您将缓冲区的大小指定为 1,这就是您一次获得一个字节的原因,这应该有所不同,在您的情况下,例如BufferedInputStream
BufferedInputStream b = new BufferedInputStream(input, 1024);
评论
请注意,它并不总是读取到它自己的内部缓冲区。BufferedInputStream
如果你查看构造函数的源代码,你会看到当你在内部分配时,它会创建一个内部缓冲区:new BufferedInputStream(input, 1)
buf = new byte[1];
BufferedInputStream b = new BufferedInputStream(input, 1);
// Internally causes b.buf = new byte[1];
在运行下一行时,未从基础文件中读取任何内容:input
byte[] does = new byte[1000];
int i = b.read(does);
如果你查看源代码,你会发现它调用。通常,读取将使用内部的内容(如果可用)并复制到 .但是在第一次读取中,它是空的,因此它使用最大的缓冲区。因此,这意味着它要么被填充并被复制到,要么像您的情况一样 (1000 >= 1),因此它填充并且不填充内部 .read(byte[]ba)
BufferedInputStream.read(byte[] ba, int off, int len)
buf
buf
ba
buf
buf.length / len
buf
ba
does
buf
因此,即使您将内部缓冲区大小指定为仅 1 个字节,对基础文件的首次访问也可能最多为 1000 字节(如果可从 )。input
顺便说一句,您不应该像上面那样转换 UTF8 流,因为您可能会在 UTF-8 字符编码的中途损坏输入流 - 显然改用。Reader
评论
input
int ch = b.read()
评论
InputStream.read(byte[])
read
BufferedInputStream