输入流之顶层抽象InputStream

该类是所有二进制输入流的的抽象父类

类中主要方法解释说明如下

(1)public abstract int read() throws IOException;

  该方法是从输入流中读取下一个字节,返回的值字节是一个范围从0到255之间的int数。如果读到输入流的未尾,则返回-1。 同时该方法会一直阻塞直到输入流中数据可用,或者流读完毕或者抛出异常。

下面以FileInputStream来举个示例。

读取一个文件test.txt. 该文件内容“abcdefghijklmn”

  @Test
    public void testRead() throws IOException {
        FileInputStream inputStream = new FileInputStream("E:\360downloads\wpcache\srvsetwp\test.txt");
        while (true) {
            int read = inputStream.read();
            if (read == -1) {
                break;
            }
            System.out.println(read + "," + (char) read);
        }
    }

打印结果如下: 

97,a
98,b
99,c
100,d
101,e
102,f
103,g
104,h
105,i
106,j
107,k
108,l
109,m
110,n

(2)public int read(byte b[]) throws IOException;

  从输入流中读取一些字节存储到b数组中,返回实际读取的长度。如果b的大小为0,则不会从输入流中读取字节,否现读取的第一个字节放入b[0],第二个字节放b[1] ,依次类推,该方法也是阻塞的,直到流读可用,或者读完,或者抛异常。

示例1:  

   @Test
    public void testReadBytes() throws IOException {
        FileInputStream inputStream = new FileInputStream("E:\360downloads\wpcache\srvsetwp\test.txt");
        byte[] buf = new byte[100];
        int read = inputStream.read(buf);
        System.out.println(read);  //14
        String readContent = new String(buf, 0, read);
        System.out.println(readContent); //abcdefghijklmn
    }

示例2:

 @Test
    public void testReadBytes() throws IOException {
        FileInputStream inputStream = new FileInputStream("E:\360downloads\wpcache\srvsetwp\test.txt");
        byte[] buf = new byte[5];
        int read = inputStream.read(buf);
        System.out.println(read);  //5
        String readContent = new String(buf, 0, read);
        System.out.println(readContent); //abcde
    }

示例3:

 @Test
    public void testReadBytes() throws IOException {
        FileInputStream inputStream = new FileInputStream("E:\360downloads\wpcache\srvsetwp\test.txt");
        byte[] buf = new byte[5];
        int len = 0;
        while ((len = inputStream.read(buf)) != -1) {
            String readContent = new String(buf, 0, len);
            System.out.println(readContent);
        }

    }

示例3打印结果:

abcde
fghij
klmn

由示例3可知,read(byte b[])方法,每次都会从输入流中读取b.length个字节,下次读流时,接着上一次的未尾开始。

(3)public long skip(long n) throws IOException;

   从输入流中跳过n个字节或者说是丢弃掉n个字节

  @Test
    public void testSkip() throws IOException {
        FileInputStream inputStream = new FileInputStream("E:\360downloads\wpcache\srvsetwp\test.txt");
        byte[] buf = new byte[14];
        long skip = inputStream.skip(4); 
        System.out.println("skip:"+ skip); // skip:4

        int read = inputStream.read(buf);
        System.out.println("read:"+read); //read:10

        String readContent = new String(buf, 0, read);
        System.out.println(readContent); //efghijklmn
    }

从上面的打印结果可知,skip确实丢弃掉了4个字节(abcd), 后面read时直接从输入流中的第5个字节开始读取,所以最终打印是“efghijklmn”

(4)public int available() throws IOException ;

    检测输入流中还可以read读取的字节个数

 @Test
    public void testAvailable() throws IOException {
        FileInputStream inputStream = new FileInputStream("E:\360downloads\wpcache\srvsetwp\test.txt");

        int available = inputStream.available();
        System.out.println("第一次测试available:"+available);  //第一次测试available:14

        long skip = inputStream.skip(4);
        System.out.println("skip:" + skip); // skip:4

        available = inputStream.available();
        System.out.println("第二次测试available:"+available); // 第二次测试available:10

        byte[] buf = new byte[5];
        int read = inputStream.read(buf);
        System.out.println("read:" + read); //read:10

        available = inputStream.available();
        System.out.println("第三次测试available:"+available);  //第三次测试available:5

        String readContent = new String(buf, 0, read);
        System.out.println(readContent); //efghijklmn
    }

由打印结果,可以很容易的理解available()方法的含义。

第1次 inputStream中可读字节14;skip丢弃掉4个字节后,第2次 检测 inputStream中可读字节等于 14 - 4 = 10 个; 然后从inputStream中read读取5个字节后,第3次打印 只剩5个可用字节了。

(5)public synchronized void mark(int readlimit) ;

  

先来做一个测试:

 @Test
    public void testMarks() throws IOException {
        FileInputStream inputStream = new FileInputStream("E:\360downloads\wpcache\srvsetwp\test.txt");

        byte[] buf = new byte[5];
        int read = inputStream.read(buf);
        // 第1次从inputStream流中读5个字节
        System.out.println(new String(buf,0,read));
        // 打个标识
        inputStream.mark(5);
        // 第2次从inputStream流中读取5个字节
        int secondRead = inputStream.read(buf);
        System.out.println(new String(buf,0,secondRead));

        // 第3次从inputStream流中读取4个字节(只剩下4个字节了)
        int thirdRead = inputStream.read(buf);
        //注意:这里不要用buf.length, 因为本次没有5个字节,不能将第2次读取到buf数组中的值全部覆盖
        System.out.println(new String(buf,0,thirdRead));
    }

本次实验,第1次读取inputStream中的前5个字节 , 第2次读取inputStream中的6到10个字节, 第3次读取inputStream中未尾4个字节 , remark()方法好像没有啥用吧。好像还真的是,不过请先看看markSupported()方法

请看下面测试:

 @Test
    public void testMarkSupport() throws IOException {
        FileInputStream inputStream = new FileInputStream("E:\360downloads\wpcache\srvsetwp\test.txt");
        boolean b = inputStream.markSupported();
        System.out.println(b); //false
    }

上次测试打印false ,  表示FileInputStream这种类型的流,根本就不支持mark()或者reset()方法。所以,尴尬。。。

下面找一个支持mark(),reset()的输入流是测试一把

 @Test
    public void testMarkAndReSet() throws Exception{
        String content = "abcdefghijklmn";
        InputStream inputStream = new ByteArrayInputStream(content.getBytes());

        System.out.println("是否支持mark:"+ inputStream.markSupported()); //是否支持mark:true
        byte[] buf = new byte[5];
        int read = inputStream.read(buf);
        // 第1次从inputStream流中读5个字节
        System.out.println(new String(buf,0,read));  //abcde
        // 打个标识
        inputStream.mark(5);
        // 第2次从inputStream流中读取5个字节
        int secondRead = inputStream.read(buf);
        System.out.println(new String(buf,0,secondRead)); // fghij

        // 重置
        inputStream.reset();

        // 第3次从inputStream流中读取5个字节
        int thirdRead = inputStream.read(buf);
        System.out.println(new String(buf,0,thirdRead));  // fghij

        // 第4次从inputStream流中读取5个字节
        int forthRead = inputStream.read(buf);
        System.out.println(new String(buf,0,forthRead)); //klmn


    }

哈,仔细观察打印结果,发现mark+reset后, 可以重复读取流中数据 。 其实,mark+reset就是这么点功能。

好了,InputStream这个输入流的顶层抽象类就写完了,主要也就这么几个方法!

原文地址:https://www.cnblogs.com/z-qinfeng/p/11787136.html