Java基础-IO (3)

read()
自定义的read方法输入文件,然后我们构造FileInputStream实例,通过循环调用read()方法从FileInputStream流中读取一个字节的内容。

int byteData=inputStream.read();

数据读取后可以将返回的int类型转换成char类型。

char aChar = (char) data;

如果到达流末尾时,read方法返回-1。此时则可以关闭流。
read(byte[])

InputStream包含了2个从InputStream中读取数据并将数据存储到缓冲数组中的read()方法,他们分别是:

int read(byte[]) int read(byte, int offset, int length)

一次性读取一个字节数组的方式,比一次性读取一个字节的方式快的多,所以,尽可能使用这两个方法代替read()方法。
read(byte[])方法会尝试读取与给定字节数组容量一样大的字节数,返回值说明了已经读取过的字节数。如果InputStream内可读的数据不足以填满字节数组,那么数组剩余的部分将包含本次读取之前的数据。记得检查有多少数据实际被写入到了字节数组中。
read(byte, int offset, int length)方法同样将数据读取到字节数组中,不同的是,该方法从数组的offset位置开始,并且最多将length个字节写入到数组中。同样地,read(byte, int offset, int length)方法返回一个int变量,告诉你已经有多少字节已经被写入到字节数组中,所以请记得在读取数据前检查上一次调用read(byte, int offset, int length)的返回值。

这两个方法都会在读取到达到流末尾时返回-1。

IO流异常处理

在读取文件的那个例子中,我们看read方法真实有效的代码知识try中的一部分,而实际我们写了很多异常处理的模板方法。

public static void read(File file) throws IOException { InputStream inputStream = null; try { inputStream = new FileInputStream(file); int byteData = inputStream.read(); while (byteData != -1) { logger.info("byteData={}, char result={}", byteData, (char) byteData); byteData = inputStream.read(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { inputStream.close(); } } }

在这段代码中共有4个地方可能会抛出异常,分别是new FileInputStream(file),inputStream.read(),inputStream.read(),inputStream.close()。
想象一下,从try块内部抛出异常。然后finally执行该块,而从finally块抛出的异常如果我们不捕获的话,将在调用堆栈中向上传播。
try-catch-finally结构显示的关闭流显得单调乏味,并且异常捕获模板代码众多,看着一点都不优雅。在java7后可以使用try-with-resource结构来处理,示例如下:

public static void read1(File file) throws IOException{ try(InputStream inputStream=new FileInputStream(file)){ int byteData = inputStream.read(); while (byteData != -1) { logger.info("byteData={}, char result={}", byteData, (char) byteData); byteData = inputStream.read(); } } }

我们在read1方法中实现了和read方法一样的功能,但代码显得简洁明了。其中在try()括号内创建了FileInputStream这个资源,当程序执行离开try{}块时,该资源将会自动关闭。如果try()括号内有多个资源,资源将按与括号内创建/列出顺序相反的顺序关闭。
IO流中,资源之所以会自动关闭,是因为IO流(包括InputStream,OutputStream,Reader,Writer)均实现了AutoClosable接口,具体可参考全局类图。我们也可以将自定义类实现AutoClosable接口,然后
与try-with-resource结构一起使用。

FilterInputStream

FilterInputStream主要有4个子类,可以用来修改InputStream的内部行为。

4个字类添加的功能如下:

类名   功能  
DataInputStream   与DataOutputStream配合使用,以一种"可携带的方式(portable fashion)"从流里读取基础类型  
BufferedInputStream   从缓冲区读取,而不是每次要用数据的时候都要进行物理读取  
LineNumberInputStream   跟踪输入流的行号;有getLineNumber( )和setLineNumber(int)方法  
PushbackInputStream   有一个"弹压单字节"的缓冲区,这样你就能把最后读到的那个字节再压回去。  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwjswp.html