该类是所有二进制输入流的的抽象父类
类中主要方法解释说明如下
(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这个输入流的顶层抽象类就写完了,主要也就这么几个方法!