java io之输入字节流总结

一、InputStream

                所有输入字节流的父抽象类,包括read(),skip(),available(),close(),mark(),reset()等方法

二、FileInputStream

                正常的文件输入字节流,每调用一次read(),读取一个字节,直接再磁盘上进行操作,可以读取一个字节或几个字节。

        FileInputStream is = new FileInputStream(file);
        try {
                while ((count = is.read(b)) != -1) {
                    String string = new String(b, 0, count);
                    System.out.println(string);
                }
                is.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        此输入字节流也可以将字符打印出来,因为使用的String构造函数String string = new String(b, 0, count);将b字符串通过默认编码打印出来

三、ByteArrayInputStream

                字节数组输入流在内存中创建一个字节数组缓冲区,可以使用构造函数来确定字节缓冲区的大小,然后从输入流读取的数据(如果是字符,则通过编码转化为字节)保存在该字节数组缓冲区中。输出时,将缓冲区的所有字节通过编码转化为字符,再进行打印

四、SequenceInputStream

                对多个流进行合并。当我们需要从多个输入流中向程序读入数据,可以使用合并流,将多个输入流合并成一个SequenceInputStream流对象。SequenceInputStream会将与之相连接的流集组合成一个输入流并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末 尾为止。 合并流的作用是将多个源合并合一个源。

五、PipedInputStream

                在java中,PipedOutputStreamPipedInputStream分别是管道输出流和管道输入流。它们的作用是让多线程可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedOutputStream和PipedInputStream配套使用。

                使用管道通信时,大致的流程是:我们在线程A中向PipedOutputStream中写入数据,这些数据会通过connect()方法自动的发送到与PipedOutputStream对应的PipedInputStream中,进而存储在PipedInputStream的缓冲中;此时,线程B通过读取PipedInputStream中的数据。就可以实现,线程A和线程B的通信。

六、ObjectInputStream

                    对象的输出流将指定的对象写入到文件的过程,就是将对象序列化的过程,对象的输入流将指定序列化好的文件读出来的过程,就是对象反序列化的过程。内部使用了DataInputStream实现。

             ObjectInputStream能够让你从输入流中读取Java对象,而不需要每次读取一个字节。你可以把InputStream包装到ObjectInputStream中,然后就可以从中读取对象了

1、如果对象需要被写出到文件上,那么对象所属的类必须要实现Serializable接口。 Serializable接口没有任何的方法,是一个标识接口而已。

2、对象的反序列化创建对象的时候并不会调用到构造方法

3. serialVersionUID 是用于记录class文件的版本信息的,serialVersionUID这个数字是通过一个类的类名、成员、包名、工程名算出的一个数字。

4. 使用ObjectInputStream反序列化的时候,ObjeectInputStream会先读取文件中的serialVersionUID,然后与本地的class文件的serialVersionUID进行对比,如果这两个id不一致,反序列则失败。

5. 如果序列化与反序列化的时候可能会修改类的成员,那么最好一开始就给这个类指定一个serialVersionUID,如果一类已经指定的serialVersionUID,然后在序列化与反序列化的时候,jvm都不会再自己算这个 class的serialVersionUID了。

6. 如果一个对象某个数据不想被序列化到硬盘上,可以使用关键字transient修饰。

7. 如果一个类维护了另外一个类的引用,则另外一个类也需要实现Serializable接口。

七、FilterInputStream

         继承了InputStream类,但是无法被实例化,也就是无法FilterInputStream f = new FilterInputStream(),因为源码中FilterInputStream的构造函数是protected类型,只能被它所在包的类和方法进行调用,所以每次想要使用FilterInputStream的方法时,必须实例化它的子类,也就是FilterInputStream f = new BufferedInputStream(),(或者其他的子类,如DataInputStream)


继承FilterInputStream的类

八、BufferedInputStream

        BufferedInputStreamFileInputStream的不同点在于,BufferedInputStream每次磁盘io时读取的byte[]数组很多,默认大小是8192,也就是有一个8M的缓冲区,而FileInputStream的read()方法(native方法)每次只从磁盘读取一个字节,即使是readBytes()方法(也是native方法)每次也只从磁盘读取几个字节。小数据读取可能没什么影响,当数据量很大时,不断的磁盘io会使整个读取速度慢很多。而BufferedInputStream由于有一个很大的内存缓冲区,磁盘io次数会少很多,因此速度会快很多。

        BufferedInputStream没有默认构造函数,参数必须是FileInputStream的实例,用到了设计模式的装饰者模式

九、DataInputStream

        DataInputStream能以一种与机器无关的方式,直接从地从字节输入流读取JAVA基本类型和String类型的数据。其他的InputStream我们只能读取byte,这个类使得我们可以直接从stream中读取intString等类型。

                同理,DataOutputStream也可以将各种JAVA基本类型和String类型写入文件中,内部也是使用的字节流,只是封装的更好了一点。

十、PushbackInputStream

        回退输入流,在JAVA IO中所有的数据都是采用顺序的读取方式,即对于一个输入流来讲都是采用从头到尾的顺序读取的,如果在输入流中某个不需要的内容被读取进来,可以使用回退输入流把读取进来的某些数据重新回退到输入流的缓冲区之中。

        PushbackInputStream也是输入流,所以内部也包含正常的数序read()、available()、skip()等方法,但是它与众不同的地方在于:有三个unread方法,用来回退,可以将已读出的字节再放回字节流中

猜你喜欢

转载自blog.csdn.net/a274537260/article/details/80358770