说起IO流,脑子里浮现出的就是inputstream,outputstream,reader,writer之类的东西,但是,这些类我们该怎么选择,他们之间有什么区别和联系,好多人却不太清楚。今天就跟大家聊聊Java的IO流。
I就是input,O就是output,IO流就是输入-输出流。输入和输出就有了一个方向的问题。一般情况下,我们所说的输入和输出都是相对于内存来说的,从外设到内存就是输入,从内存到外设就是输出。这个是从流向来区分的。还可以从操作的内容来区分,就是字符流和字节流。Java中InputStream和OutputStream就是字节流,Reader和Writer就是字符流。按照流的角色,可以分为节点流和处理流。可以从一个特定的IO设备读写数据的流就是节点流,处理流就是对已存在的数据流进行连接和封装。
Java的IO流的类都存在于java.io包中,字节流的基类是InputStream和OutputStream,字符流的基类是Reader和Writer。我们通过下表来说明一下常用的类有哪些。
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
抽象基类 | InputStream | OutputStream | Reader | Writer |
访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
访问字符串 | StringReader | StringWriter | ||
缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
转换流 | InputStreamReader | InputStreamWriter | ||
对象流 | ObjectInputStream | ObjectOutputStream |
在我们的实际工作中,最常用的就是FileReader、FileWriter来操作文件,但是两个在读取的时候只能一个字符一个字符去读,如果想读一行怎么办呢?使用BufferedReader和BufferedWriter,他们是具有缓冲的IO流,在读写文件的实现,先去操作缓冲区,缓冲区满了,再一次性的写入IO设备,此时要注意调用flush方法,否则不会自动写入IO设备中。
如下是FileReader和FileWriter的示例,在操作结束之后,一定要调用close方法,否则会发生内存泄露。一般情况下都使用try。。。catch。。。finally来实现。
FileWriter fw = null; FileReader fr = null; try { //创建写文件 fw = new FileWriter(new File("1.txt")); //向文件中写入字符串 fw.write("hello,welcome"); //调用flush方法,将内容写到文件 fw.flush(); //创建读文件 fr = new FileReader(new File("1.txt")); //创建缓冲区,用于接收读取的字符 char[] buffer = new char[8]; StringBuilder sb = new StringBuilder(); //nRead为读取到的字符,调用read方法,返回读取到的字符个数,如果读取结束,返回-1 int nRead = 0; while( (nRead = fr.read(buffer)) != -1) { sb.append(new String(buffer,0,nRead)); } System.out.println(sb.toString()); } catch (Exception e) { e.printStackTrace(); } finally { //关闭资源 if(fw != null) { fw.close(); fw = null; } if(fr != null) { fr.close(); fr = null; } }BufferedReader和BufferedWriter的使用方法也是类似的。BufferedReader可以读取一行数据。
BufferedWriter bw = null; BufferedReader br = null; try { //创建写文件 bw = new BufferedWriter(new FileWriter("1.txt")); //向文件中写入字符串 bw.write("hello,welcome"); //调用flush方法,将内容写到文件 bw.flush(); //创建读文件 br = new BufferedReader(new FileReader("1.txt")); StringBuilder sb = new StringBuilder(); String str = null; while( (str = br.readLine()) != null) { sb.append(str); } System.out.println(sb.toString()); } catch (Exception e) { e.printStackTrace(); } finally { //关闭资源 if(bw != null) { bw.close(); bw = null; } if(br != null) { br.close(); br = null; } }初次之外,DataInputStream和DataOutputStream也是需要了解的。他们是用来对对象进行序列化的,可将一个对象已二进制的方式,写入文件,通过网络等方式进行传输后,再进行反序列化。操作的对象一定要实现java.io.Serializable接口。
以上,就是JDK提供的一些Java IO流的基本用法。在工作中,要学会使用一些工具类来简化操作,如apache的FileUtils类,IOUtils类等。在JDK1.5还有了NIO,也就是非阻塞的IO流。包括一些Netty、Mina等NIO的框架也有待于大家的了解。