转载请注明源出处: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. bootstrap-treeview的 简单使用

    理论:http://blog.csdn.net/babyxue/article/details/73835444 插依赖Bootstrap 和jQuery <link href="~/ ...

  2. 创建template模板

    创建一个自己常用的快捷键的模板. 1.选择window-->preferrence--搜索temp--java 2.点击new 3.根据自己的习惯起一个名字 4.比如syso 5.语法不会,就找 ...

  3. UVa 11280 Flying to Fredericton (DP + Dijkstra)

    题意:给出n(2<=n<=100)个城市之间的m(0<=m<=1000)条航线以及对应的机票价格,要求回答一些询问,每个询问是给出最大停留次数S,求从其实城市Calgary到终 ...

  4. Airplace平台

    Demo: 左上角:(0, 0)开始导航,手机终端上实时在地图上当前所在显示,当前点以绿色点显示,轨迹点以红色显示. 系统架构:基于移动手机的以网络为辅助的架构.特点:低头顶交流,用户隐私和安全 &g ...

  5. yum 常用命令

    yum是一个用于管理rpm包的后台程序,用python写成,可以非常方便的解决rpm的依赖关系.在建立好yum服务器后,yum客户端可以通过 http.ftp方式获得软件包,并使用方便的命令直接管理. ...

  6. Android ContentProvider和Uri详解

    一.使用ContentProvider(内容提供者)共享数据 ContentProvider在android中的作用是对外共享数据, 也就是说你可以通过ContentProvider把应用中的数据共享 ...

  7. El中调用java静态方法

    最近在项目中遇到需要调用静态方法的问题,形如: <c:forEach items="beans" var="bean"> <p>总数:$ ...

  8. ThinkPad T430i,如何将WIN8换成WIN7???

    1. 启动时不断点击键盘上的F1键,进入BIOS 界面选择“Restart”→把 “OS Optimized Default”设置为 “disabled” ,(OS Optimized Default ...

  9. MySql数据库远程连接失败问题解决

    例如,你想myuser使用mypassword从任何主机连接到mysql服务器的话. GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'%' IDENTIFIED BY ...

  10. C# 创建、部署和调用WebService简单示例

    webservice 可以用于分布式应用程序之间的交互,和不同程序之间的交互. 概念性的东西就不说太多,下面开始创建一个简单的webservice的例子.这里我用的是Visual Studio 201 ...