说起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的框架也有待于大家的了解。