转载请注明源出处: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. Gridview的RowDataBound事件可以做很多事情

    protected void gvTest_RowDataBound(object sender, GridViewRowEventArgs e)        {            //如果是绑 ...

  2. Facebook支撑万亿Post搜索背后的技术窥探

    转自http://www.csdn.net/article/2013-10-29/2817333-under-the-hood-building-posts-search 近日,Facebook为po ...

  3. Sql Server 2008 压缩数据库日志文件

    第一步:将数据库设置为简单模式 选中数据库点右键->属性: 第二步:收缩数日志文件 1, 2,   第三步:将恢复模式改回为完整模式     如果你觉得用UI界面麻烦,那你就用SQL语句吧   ...

  4. ReactJS 官网案例分析

    案例一.聊天室案例 /** * This file provided by Facebook is for non-commercial testing and evaluation * purpos ...

  5. Transaction And Lock--使用资源锁来控制并发

    写过程序的朋友都知道,在多线程处理时,对于非线程安全的对象,需用使用锁定特定对象(LOCK)的方法来保证串行操作.曾经有位开发询问我,在SQL Server内部是否有类似的实现方法来控制某一操作不能并 ...

  6. 仿建设银行APP首页效果

    仿建设银行APP首页效果 下载地址: http://pan.baidu.com/s/1eRMYEzC 下载后需要解压,解压密码联系:390980233  收费88元 HTML+JS实现,下载即可试用. ...

  7. Struts2-057/CVE-2018-11776两个版本RCE漏洞分析(含EXP)

    0x01 前言 2018年8月22日,Apache Strust2发布最新安全公告,Apache Struts2存在远程代码执行的高危漏洞(S2-057/CVE-2018-11776),该漏洞由Sem ...

  8. ASP.NET Core SignalR CORS 跨域问题

    将 SignalR 集成到 ASP.NET Core api 程序的时候,按照官方 DEMO 配置完成,本地访问没有问题,但是发布之后一直报跨域问题,本地是这样设置的: 原始代码: services. ...

  9. .netcore部署centos

    前言:最近公司有个项目用 .netcore开发的项目,然后闲的没事就研究如果发布到Linux系统上 需要安装的插件以及支撑架构 1.dotnetSDK 2.jexus Jexus 是Linux平台上 ...

  10. F#语言入门之什么是F#语言

    F#是一种函数式编程语言,可以轻松编写正确且可维护的代码. F#编程主要涉及定义类型推断和自动泛化的类型和函数. 这使您可以将焦点保留在问题域上并操纵其数据,而不是编程的细节. open System ...