PushbackInputStream和PushbackReader是Java I/O系统里两个比较让人迷惑的类,我以前对它(们)就不太了解,直到某一天看了以前水母Java版的牛人zms的评论和一些资料以后才有所获益。这是几个月以前的事情了,这几天写有关序列化的总结时才想到这也不失为一个好的话题。
一个允许你反悔的hook
Java I/O系统是一个典型的Decorator模式的实现,它以InputStream/OutputStream为基本核心,通过继承关系,不断为该核心添加新的功能,如文件流、缓冲、加解密等。对I/O系统设计模式感兴趣的话,可以参考developerWorks上的一篇文章:从Java类库看设计模式。Java I/O默认是不缓冲流的,所谓“缓冲”就是先把从流中得到的一块字节序列暂存在一个被称为buffer的内部字节数组里,然后你可以一下子取到这一整块的字节数据,没有缓冲的流只能一个字节一个字节读,效率孰高孰低一目了然。有两个特殊的输入流实现了缓冲功能,一个是我们常用的BufferedInputStream,像读文件我们常用
BufferedInputStream in = new BufferedInputStream(new FileInputStream("datafile"));
while ((b = in.read()) != -1)
{ ...
}
in.close();
这是我们几乎不用查什么JDK文档就能信手拈来的代码段,写的时候也应该思考一下套一个BufferedInputStream的意义何在。另一个就是我们不怎么看到的PushbackInputStream(其对应的字符流模式为PushbackReader)。 在通常状态下,“流”意味着“一次性”,就是说你进行了一次操作后它的状态就变了,譬如读,无论是文件还是socket,你读的过程中一个潜在的“读指针”一样的东东就在移动,你无法在读以后再重新定位(当然RandomAccessFile是另一种情况),如果你以前奇怪为什么数据库操作中ResultSet里get某个字段以后就不能再第二次get它了,这里或许是个解释。但好在PushbackInputStream给了我们第二次读的机会。我们先来区别一下“监听”和“截获”的概念,“监听”就是把得到的消息copy一份,原始消息并不作任何改变地传递到目的地;而“截获”则是先把消息“扣押”下来,不让其自动转给目标,而是先进行一些处理以后在转发给目标(如果是网络安全专业的背景知识,大概知道“监听”是对“机密性”的攻击,而“截获”不仅是对“机密性”还是对“完整性”的攻击)。有的朋友大概对hook这个名词有些了解,它是一种Windows的一种消息处理机制,似乎就是一种消息截获手段,但我对Windows编程一窍不通//shy;此外,如果你熟悉Servlet的话,也能找到像Filter这样的处理机制,在对每个HTTP请求/应答进行转发之前,先在里头耍一点花招,确定哪些予以转发,哪些屏蔽掉,这也算是“截获”吧。通过上面的介绍,我们不妨把PushbackInputStream看成是对输入流的一种“截获”手段,其中最重要的方法是unread:
public void unread(int b) throws IOException
public void unread(byte[] b) throws IOException
public void unread(byte[] b, int off, int len) throws IOException
我们可以想象一下,PushbackInputStream内置一个缓冲区(事实上,你可以从它的源代码里找到这个protected的字节数组),当低层流进来时先流进这个buffer,在你把流“物归原主”之前还有机会对它耍花招,然后再用unread方法“反悔”一下,把缓冲区里已经读过的内容(一般是没有被改动的,当然你也可以改动它,那就失去“归赵”的意义了,因为已经不是“完璧”了)再插入到流的头部,下次读的时候是流剩余的部分再加上从缓冲区“归还”的部分。上面三个unread方法分别代表从缓冲区“归还”一个字节、一个字节数组以及一个字节数组中指定的部分。 PushbackInputStream是对二进制流的处理,字符流下相对应的就是PushbackReader。
有什么用?
学过编译的话就容易理解了,比如从左向右扫描字符流“for(int i=0;i<10;i++)”,扫描到“for”是不是就可以说是个关键字了呢?不行,说不定后面是“for1”,那就是个变量而不是关键字了,知道看到“(”才恍然大悟,哦,我可以安全地说“看到for关键字”了,但“(”还得归还给输入流,因为需要后面继续扫描。在上下文相关语言里,就更需要这种补偿机制。又如,在解析HTML文档的时候,我需要根据它的“meta”标签的“charset”属性来决定使用哪种字符集进行解析,但HTML可不是“charset”而是“<html>”开头的哦!所以需要通过PushbackInputStream缓冲前面一段内容,等取到字符集名称后在把读到的流全部归还,再用指定的字符集进行解析。
源文件地址:http://www.host01.com/article/jsp/00040004/057211220911068.htm
分享到:
相关推荐
《不到1000元也“路由”——小议宽带路由器的选择》这篇文章主要讨论了在家庭、小型办公室和学校寝室等环境中,如何选择合适的宽带路由器,以实现经济、便捷的网络共享。 首先,宽带路由器的作用在于连接局域网和...
安全生产是任何行业,尤其是建筑业的核心关注点,因为它直接关乎到生命安全和企业的可持续发展。本文以"软件需要硬件来启动和运行"为引子,强调了在安全生产中法制保障的重要性,将其比喻为软件对于硬件不可或缺的...
这篇文章讨论了微课程教学法在高中地理教学中的应用,特别是以“农业的区位选择”为例进行深度学习的...这不仅是对教学法的一次深入探讨,也对教育信息化融合应用,特别是微课程的开发和实践提供了宝贵的经验和参考。
在市场经济条件下,风景区开发应遵循以风景名胜区总体规划指导风景资源向旅游资源转化,然后在旅游发展规划的指导下,将旅游资源开发成旅游产品推向市场的过程。文章同时以奉节县天坑地缝风景名胜区规划及旅游发展...
从 FPGA 到 SOPC 嵌入式系统发展朝着小体积、低功耗、高性能的趋势发展。MCU、DSP 和 FPGA 三种 处理器在现代嵌入式系统中扮演的角色呈现三分天下的局面, 它们各自具有独特的优势而在 某方面又略显不足。...
小议中华文化之精髓与糟粕——读《三字经》有感.docx
小议中华文化之精髓与糟粕——读《三字经》有感_1.docx
JavaScript 库比较 —— Dojo、jQuery 和 PrototypeJS 在当今的 Web 开发中,JavaScript 库扮演着越来越重要的角色。这些库提供了许多有用的功能,可以帮助开发者快速构建 Web 应用程序。本文将对 Dojo、jQuery 和 ...
小议外汇期权会计在新规则中应用 本文主要探讨了小议外汇期权会计在新规则中的应用,涉及到外汇期权的概念、分类、确认、计量和披露等方面的知识点。 一、外汇期权的概念 外汇期权是一种金融衍生工具,允许持有人...
### 抖动算法小议——深入探讨多媒体技术中图像的抖动算法 #### 引言 在多媒体领域,尤其是在图像处理技术中,抖动算法扮演着至关重要的角色。本文旨在通过对抖动算法的深入解析,帮助读者理解其原理及其在灰度...
小议经济型酒店消费者心理及消费方向.doc
这篇名为“让Struts 1焕发青春——小议对Struts的改造”的文章,可能探讨了如何通过一系列技术手段和策略来提升Struts 1框架的效能和安全性,使其能够更好地适应当前的开发需求。 首先,改造可能涉及到性能优化。...
"小议如何选择第三方物流供应商" 在当今竞争日趋激烈和社会分工日益细化的背景下,第三方物流表现出明显的优越性。许多企业为降低成本、提高服务水平、提升自身竞争力,将非核心竞争力的物流业务外包给第三方物流...
"小议如何选择第三方物流供应商" 一、第三方物流的涵义 第三方物流是指由供方、需方以外的第三方去完成物流服务的物流运作方式。第三方物流供应商通过合同方式与企业合作,提供专业的物流服务,帮助企业降低成本、...
标题中的“小议给力的阅读理解材料答案”表明这是一份关于阅读理解训练材料的讨论,而“江苏给力新型材料”可能是指这份材料是与江苏地区一家名为“给力新型材料”的公司相关的,或者是以该公司为背景编写的阅读理解...
其中,第二种方法——使用Matlab引擎服务,具有显著优势。它可以实现嵌入式编程,简化调试过程,充分发挥Matlab的数值计算和图形处理功能,特别适合科研和提高工作效率。 Matlab引擎采用客户机/服务器计算模式,VCC...
标题中提到的“小议二级C语言之逻辑运算符”,表明本文主要探讨C语言中的逻辑运算符相关知识点。逻辑运算符是C语言中用于执行逻辑运算的符号,主要包括逻辑与(&&)、逻辑或(||)和逻辑非(!)三种。逻辑运算符常...
小议嵌入式计算机技术.pdf
法治思想起源小议.docx
小议食品安全问题.doc