zoukankan      html  css  js  c++  java
  • 输入流之顶层抽象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这个输入流的顶层抽象类就写完了,主要也就这么几个方法!

  • 相关阅读:
    MongoDB 基础学习
    在 PostgreSQL 中使用码农很忙 IP 地址数据库
    在 MySQL 中使用码农很忙 IP 地址数据库
    编译opencv和opencv_contrib
    修改本次提交日志
    clone报告超过限制
    修改gitolite管理员
    libevent简介[翻译]11 连接监听:接收一个TCP连接
    libevent简介[翻译]11 Evbuffers:缓冲IO的功能函数
    Windows查看TCP连接数
  • 原文地址:https://www.cnblogs.com/z-qinfeng/p/11787136.html
Copyright © 2011-2022 走看看