`
ayis
  • 浏览: 186252 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

今天终于明白了什么是缓冲流

    博客分类:
  • java
阅读更多
原文地址:原来BufferedReader不能和InputStream交替使用(转)

原文是这样的意思,用BufferedReader封装一个InputStream,再用DataInputStream封装这个InputStream,这样做之后,先用BufferedReader从流中读取一行,然后分别用这个InputStream读取一个字符和DataInputStream读取一行,再用BufferedReader读取一行,结果BufferedReader均能读到数据,而InputStream和DataInputStream均读不到数据.数据流中只有40多个字符。这说明了,BufferedReader第一次读取时,就把这40多个字符都读取出来,缓冲起来了,后面每次读的时候,都只是从缓冲里拿出来。40多个字符就一次被BufferedReader读进去缓存起来了,所以InputStream和DataInputStream就都读不到字符了。
原文并猜想,如果流中的数据够多到BufferedReader缓存不下来的时候,InputStream和DataInputStream就能读到数据了。

确实是这样的,在BufferedReader的源码中,有
private static int defaultCharBufferSize = 8192;

这个是默认缓冲区的大小,BufferedReader一次读取时,能缓存这么多个字符。

我对原文的程序修改了一下:
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class TestByteArray {

	public byte[] generateByte() {
		// 构造一个测试流,这样就不用从文件里面读取了,在这个流里面使用了大量的回车换行("\r\n"),这样方便过会的测试
		// 过会,我会通过把字符串转换成byte数组,然后通过ByteArrayInputStream来构造一个数据流
		String str = "a\r\nbc\r\ndef\r\nghi\r\nj\r\nklmn\r\nopqr\r\ns\r\ntuvwx";	// 这个字符串的长度是40个。	
		StringBuffer buffer = new StringBuffer();
		// 通过循环,返回足够大的字符数据
		for(int i=0 ; i < 205; i++){
			buffer.append(str);
		}
		str = buffer.toString();
		System.out.println(str.length());			// 打印字符串的长度
		return str.getBytes();
	}

	public static void main(String[] args) throws IOException {
		
		TestByteArray self = new TestByteArray();
		byte[] be = self.generateByte();
		InputStream in = new ByteArrayInputStream(be);
		BufferedReader bufferReader = new BufferedReader(new InputStreamReader(
				in));
		// 使用DataInputStream而不直接使用Inputstream是因为这样方便,因为他提供了读取行
		// 不过听说他读取行时把字节转变为字符时会有问题,所以不推荐使用,不过我们在这只做测试就没关系了
		DataInputStream dataInputStream = new DataInputStream(in);

		// 先读取流里面的一行数据
		System.out.println("bufferReader=" + bufferReader.readLine());
		// 回过头来使用dataInputStream读取数据,会发现什么也读取不到
		System.out.println("dataInputStream=" + dataInputStream.readLine());
		// 回过头来使用inputstream读取数据,会发现什么也读取不到
		System.out.println("in=" + in.read());
		// InputStream读取不到数据,然后再使用原来的BufferedReader来读取数据,发现是接着原来读取的.
		System.out.println("bufferReader=" + bufferReader.readLine());

		// 我们上面的字符串比较小,我想如果字符串,大到缓存装不下的时候,使用inputstream回头去读取数据,肯定是能读取到的
		// 这个我就不测试了

	}

}


在这个修改后的程序中,通过循环,返回足够大的字符串,8200个,超过了BufferedReader的默认缓存,结果InputStream和DataInputStream就都能读到字符了。运行这个程序结果如下:
8200
bufferReader=a
dataInputStream=s
in=116
bufferReader=bc

修改循环的次数为204,字符串的长度为8160,它小于8192,结果InputStream和DataInputStream就均读不到数据了。

这足以说明,BufferedReader是把数据缓存起来了,并且缓存的大小是8192个字符。

分享到:
评论

相关推荐

    浅谈带缓冲I/O 和不带缓冲I/O的区别与联系

    首先要明白不带缓冲的概念:所谓不带缓冲,并不是指内核不提供缓冲,而是只单纯的系统调用,不是函数库的调用。系统内核对磁盘的读写都会提供一个块缓冲(在有些地方也被称为内核高速缓存),当用write函数对其写...

    浅谈c++中的while(cin)问题

    一直不明白未什么,解释请看下。 输入缓冲是行缓冲。当从键盘上输入一串字符并按回车后,这些字符会首先被送到输入缓冲区中存储。每当按下回车键后,cin.get() 就会检测输入缓冲区中是否有了可读的数据。cin.get()...

    数据采集之Flume.xmind

    提示 学习Flume必须明白这几个概念,Event英文直译是事件,但是在Flume里表示数据传输的一个最小单位(被Flume收集的一条条日志又或者一个个的二进制文件,不管你在外面叫什么,进入Flume之后它就叫event)。...

    用C++实现简单的文件IO操作

    现在继续文件输入, 需要一点技巧, 所以先确认你已经明白了流操作,对 "和"&gt;&gt;" 比较熟悉了, 因为你接下来还要用到他们。继续…  二、ASCII 输入  输入和"cin" 流很像. 和刚刚讨论的输出流很像, 但你要考虑几件...

    小日本视频转换器

    7)VBV缓冲区大小:缓冲区大的话,编码优化会好一些,但是解码的时候也要求大一些的缓冲区。因此,vcd/svcd标准中参数是固定的,否则可能机器无法播放。 8)Pofile & level(类别与级别): 这个参数是mpeg1没有的。...

    Tinyxml 源代码(VC6 & VS2005)

    TiXmlPrinter:输出到一个std::string或者内存缓冲区中。 API还不是很简练。 将来会增加打印选项。 在将来的版本中可能有些细微的变化,因为它会被改进和扩展。 流 设置了TIXML_USE_STL,TinyXML就能支持C++流...

    Java服务器端开发面试.doc

    Java服务器端开发面试题 Java服务器端开发面试题篇1 Hashcode()和equals(), 明白背后的原理,包括hashcode()的用法,各自的区别,如何,何时覆盖,为何覆盖 区别new String()和 申明的字符串的区别,String不变量,堆...

    C语言FAQ 常见问题列表

    o 2.2 64 位机上的 64 位类型是什么样的? o 2.3 怎样定义和声明全局变量和函数最好? o 2.4 extern 在函数声明中是什么意思? o 2.5 关键字 auto 到底有什么用途? o 2.6 我似乎不能成功定义一个链表。我试过 ...

    你必须知道的495个C语言问题(PDF)

    2.2 为什么struct x f . . . g; x thestruct; 不对? . . . . . . . . . . . . . 7 2.3 一个结构可以包含指向自己的指针吗? . . . . . . . . . . . . . . . 7 2.4 在C 语言中实现抽象数据类型什么方法最好? . . . ....

    操作系统(内存管理)

    为什么必须管理内存 内存管理是计算机编程最为基本的领域之一。在很多脚本语言中,您不必担心内存是如何管理的,这并不能使得内存管理的重要性有一点点降低。对实际编程来说,理解您的内存管理器的能力与局限性至关...

    示波器太昂贵,国外开源教你拥有自己的示波器!-电路方案

    在处理ADC高速率采集的大码流的时候,ADC的数字输出连接到一个来自IDT的高速FIFO存储器IDT7201(长达512字节),当存储器的缓冲区写满后,整个内存的内容被放到微控制器的内存,在那里对其中的样品进行进一步处理,...

    自己动手写操作系统(含源代码).part2

    在我写作《自己动手写操作系统》的时候,并没有想过今天会有一个第二版。原因在于,我希望这本书是用来填补空白的,而不是重复去做别人已经做得很好的事情。所谓填补空白,具体说就是让像我一样的操作系统爱好者在...

    自己动手写操作系统(含源代码).part1

    在我写作《自己动手写操作系统》的时候,并没有想过今天会有一个第二版。原因在于,我希望这本书是用来填补空白的,而不是重复去做别人已经做得很好的事情。所谓填补空白,具体说就是让像我一样的操作系统爱好者在...

    飞鸽传书(IPMessenger) 源码

     - 其它功能都很容易理解, 你试一试就明白了 操作技巧  1、隐藏/显示窗口Ctrl+D  2、按住Ctrl键再点[刷新]可保持现有用户,搜索新上线的用户  3、打开发送/接收消息窗口Ctrl+Alt+S/R(需要进行详细设置)  4、...

Global site tag (gtag.js) - Google Analytics