转载请注明源出处:http://www.cnblogs.com/lighten/p/7063161.html

1.前言

  之前的章节已经介绍了java的io包中所有成对(输入、输出对应)的字节流,本章介绍剩余的一些字节流,包括:LineNumberInputStream、SequenceInputStream、StringBufferInputStream。在JDK8的版本中,只有中间的SequenceInputStream没有被废弃,其它两个都被指出已废弃了。

2.LineNumberInputStream

  这个输入流通过添加函数功能,能保持对输入流的行数的追踪。行号从0开始,每次增加1。顺便说一下,这个类是在JDK1.0就存在了。被废弃的原因在类的注释中也给出了:这个类错误地假设bytes能够足够表示characters。在JDK1.1中,也就是此类后面的版本,更好的方式来操作字符流就是创建一个新的字符流,这个流中包含了一个用于计算行号的类。这也就是在JDK1.1中出现的LineNumberReader,此节不讲,是字符流的内容。

  LineNumberInputStream继承于FilterInputStream,类结构如下:

  可以看出,对于抽象父类InputStream,其多了set和get行号的两个方法。下面先看基本的数据流的方法实现。

  之前看的结构图有四个变量,两个一组应该很好理解,mark开头的主要是让Inputstream的mark()方法使用,记录一下。lineNumber就是记录的行号了,pushBack有什么作用呢?看上图的read逻辑。pushBack默认情况下为-1,-1的时候就读取一个,不是-1的时候就返回这个暂存的值。读取一个字节会判断其是否是\n,是行号就直接加1了,如果是\r,就让pushBack再读一个,如果是\n就重置为-1。这段写的很绕,通俗的说就是:read()方法是读取一个字节,我们都知道流读取了就不能再读取,但是判断换行符的时候就麻烦了,\r的时候需要判断一下下一个是否是\n,所以需要再读取一个字节,这个时候就要保存一下这个字节了,就存在pushback中,pushback一般都是-1,意味着直接读一个就可以了,不是-1的时候就是说之前判断的是\r,但下一个不是\n,所以保存了一下这个非\n的字符,本次就直接返回了。上面有一个坑的地方,其判断了\r之后就还会执行\n,因为没有break。这会造成下例效果:

    @Test
public void test() throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream("123\r\t\n456\r\n789\r\n".getBytes());
LineNumberInputStream lnis = new LineNumberInputStream(bais);
byte[] buffer = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int length;
while((length = lnis.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
System.out.println(new String(baos.toByteArray()));
System.out.println(lnis.getLineNumber());
}

  多出现了一个空行。实际上面确实\r\t\n,这个产生了两个回车,实际上直接输出也是两个回车。(-。-)!!!可能废弃的真正原因就如上所说的byte不能表示所有的字符吧。

3.SequenceInputStream

  一个SequenceInputStream表示其他输入流的逻辑连接。它从一个有序的输入流开始,从第一个开始直到到达文件的末尾,然后从第二个文件中读取,以此类推,直到最后一个包含的输入流到达文件的末尾。

  这个流很简单,结构如下:

  就是接受了一组有序的输入流,读取的时候,一个个读到为罢了。

  像接力棒一样,读完一个又接一个,知道全部读取完毕。

    @Test
public void test2() throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream("你好".getBytes());
ByteArrayInputStream bais2 = new ByteArrayInputStream(",张三".getBytes());
SequenceInputStream sis = new SequenceInputStream(bais, bais2);
byte[] buffer = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int length;
while((length = sis.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
System.out.println(new String(baos.toByteArray()));
}

4.StringBufferInputStream

  这个流也是一个废弃的方法,其理由是:这个类不能正确地将字符转换成字节。在JDK 1.1中,从字符串创建流的首选方法是通过StringReader类。

  这个类允许应用程序创建一个输入流,其中读取的字节是由字符串的内容提供的。应用程序还可以使用ByteArrayInputStream从字节数组中读取字节。这个类只使用字符串中每个字符的低8位。结构也很简单:

  buffer就是缓存的字符串,count就是这个字符串的长度了。read()方法就是将字符串按字节读取:

  官方虽然给出了这两个流被废弃的原因,就是字符和字节之间的转换问题,但是个人还是不明白哪里会出问题,对编码还是所知甚少,目前最大的困惑就是所有的流都是以-1为结束标志符,C语言的文件流EOF也是-1,为什么不怕中间有个字节正好是-1呢?这里有篇文章说了一下这个问题:http://blog.csdn.net/jkler_doyourself/article/details/5645925。没有完全理解,但是-1是0xFFFFFFFF,而很多流读取的时候都&0xFF,测试如下:

    @Test
public void test3() {
byte[] a = new byte[]{-1};
ByteArrayInputStream bis = new ByteArrayInputStream(a);
System.out.println(bis.read());
}

  -1读出来是255。问题的根本在于并不是说读取到-1,主要的判断还是是否结束了,即再取值是否能取到,或者是已知其是否结束。这个方法才是判断流是否结束了,返回-1。而其它情况&0xFF之后就不会表现成-1了,-1是0xFFFFFFFF。这也是一个比较重要的手段。当然实际上值并没有改变,因为你再强转成byte又回到了-1,这里返回int也就规避了这个问题,取了int的0~255范围,所以你能够通过使用read()!=-1来判断结尾,再通过强转回byte变成原有的值。我个人是这么理解的。如有错误,请指教一下。

Java之IO(九)其它字节流的更多相关文章

  1. java的IO流,字节流和字符流

    java操作文件都是通过流来处理的,(其实其他很多语言也是这样) 第一:java的IO流,分为:输入流 和 输出流(这真是废话,这是从流向的角度来说的) 第二:java的所有IO流,只分为:字节流 和 ...

  2. Java【IO流、字节流、字符流】

    1.内存是临时存储 Input输入(读取) output输出(输出) 流:数据(字符字节)1个字符=2个字节 1个字节=8个二进制位 输入:把硬盘中的数据读取到内存中 输出:把内存中的数据写入到硬盘中 ...

  3. Java基础IO流(二)字节流小案例

    JAVA基础IO流(一)https://www.cnblogs.com/deepSleeping/p/9693601.html ①读取指定文件内容,按照16进制输出到控制台 其中,Integer.to ...

  4. 十九、Java基础--------IO流之字节流

    在上一篇文章中介绍了IO体系以及一些基本概念和字符流的相关应用,本文着重介绍字节流的相关操作. 字节流 它的操作与字符流类似,可以参与字符流的定义.读取.写入.处理异常的格式,只不过是处理的数据不同, ...

  5. Java:IO流之字节流InputStream、OutputStream详解

    字节流: (抽象基类)InputStream类(读): (抽象基类)OutputStream类(写):   InputStream: 构造方法摘要 InputStream()              ...

  6. 【java】io流之字节流转为字符流:java.io.OutputStreamWriter和java.io.InputStreamReader

    package 文件操作; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; impo ...

  7. java的IO操作:字节流与字符流操作

    流的概念 程序中的输入输出都是以流形式,流中保存的实际上都是字节文件. 字节流与字符流 字节流的操作: 1)输入:inputStream, 2)输出:outPutStream; 字符流的操作: 1)输 ...

  8. Java之IO初识(字节流和字符流)

    IO概述 生活中,你肯定经历过这样的场景.当你编辑一个文本文件,忘记了 ctrl+s ,可能文件就白白编辑了.当你电脑上插入一个U盘,可以把一个视频,拷贝到你的电脑硬盘里.那么数据都是在哪些设备上的呢 ...

  9. java的IO学习,字节流与字符流的编码讲解

    字节流与字符流 字节流可以处理所有类型的数据(图片.视频等),在java中对应的类都为“stream”结尾 1字节=8位二进制=具体存储空间   字符流仅能处理纯文本的数据,在java中对应的类都是以 ...

随机推荐

  1. Django入门与实践-第11章:URL 分发(完结)

    http://127.0.0.1:8000http://127.0.0.1:8000/boards/1/http://127.0.0.1:8000/boards/2/http://127.0.0.1: ...

  2. MySQL 的IFNULL()、ISNULL()和NULLIF()函数

    参考与http://blog.csdn.net/xingyu0806/article/details/52080962 IFNULL(expr1,expr2) 假如expr1不为NULL,则 IFNU ...

  3. 20155218 2016-2017-2 《Java程序设计》第8周学习总结

    20155218 2016-2017-2 <Java程序设计>第8周学习总结 教材学习内容总结 java.util.logging包提供了日志功能相关类与接口,不必额外配置日志组件,就可以 ...

  4. hdu1257 最少拦截系统(贪心) 2016-05-19 20:28 90人阅读 评论(0) 收藏

    最少拦截系统 Problem Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能 ...

  5. hdu 5068 线段树维护矩阵乘积

    http://acm.hdu.edu.cn/showproblem.php?pid=5068 题意给的略不清晰 m个询问:从i层去j层的方法数(求连段乘积)或者修改从x层y门和x+1层z门的状态反转( ...

  6. hdu 4994 前后有序Nim游戏

    http://acm.hdu.edu.cn/showproblem.php?pid=4994 Nim游戏变成从前往后有序的,谁是winner? 如果当前堆数目为1,玩家没有选择,只能取走.遇到到不为1 ...

  7. What if you are involved in an automobile accident in the US

    What if you are involved in an automobile accident in the US With increasing Chinese tourists and vi ...

  8. vim 安装vim-javascript插件--Vundle管理

    最近看了一下node.js,但是写的时候,vim对js没有很好的提示.于是就安装插件来处理,准备安装vim-javascript.但是安装github上面的插件时,推荐用Vundle和pathogen ...

  9. AndroidPn服务端部分bug解决方案

    目前推送的情况已经大致可以了,可以正常推送.但是要在实际生产中使用,要改进很多地方. 原本的版本,是不会对消息重新发送的.消息如果丢失,或者用户没有在线,消息也不会重新的发送.所以,这些问题都是要解决 ...

  10. LeetCode141:Linked List Cycle

    题目: Given a linked list, determine if it has a cycle in it. Follow up: Can you solve it without usin ...