Java中的IO流总结
IO可以分为文件IO和Socket IO,本篇主要总结文件IO。
一、常用的流
下图就是Java中常见的文件IO流。
1.流的分类
①输入流和输出流。
按照流向:可分为输入流和输出流。
这里输入输出涉及到方向问题,通常是以内存(程序运行在内存)的角度来考虑的。所以,从硬盘到内存是内存输入,从内存到硬盘是输出。
如果数据是从服务器端到客户端,这种情况下,服务端的内存负责将数据输出到网络里,所以是输出,Client端的内存负责从网络读取数据,因此是输入。
②字节流和字符流
字节流操作的是8位的字节(1Byte),而字符流操作的是16位的字符(2Byte)。
③节点流和处理流
按照流的角色来分,可以分为节点流和处理流。
可以从/向一个特定的IO设备(如磁盘,网络)读/写数据的流,称为节点流,节点流也被成为低级流。
处理流则用于对已存在的流进行连接或封装,顾名思义,处理就是对流进行功能处理。处理流也被称为高级流。实际上,Java使用处理流来包装节点流是一种典型的装饰器模式,通过使用处理流来包装不同的节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。因此,处理流也被称为包装流。
2.IO流的体系
访问文件:
FileInputStream,FileOutputStream
FileReader,FileWriter
RandomAccessFile:并不是流体系中的一员,其封装了字节流,同时还封装了一个缓冲区(字符数组)。可读写文件,还可以随机读写(跳转到文件的任意地方来读写数据)。
访问数组:
- 字节数组:ByteArrayInputStream, ByteArrayOutputStream
- 字符数组:CharArrayReader, CharArrayWriter
访问字符串:
StringReader,StringWriter
访问管道(管道流,用于线程间通信):
PipedInputStream,PipedOutputStream,PipedReader,PipedWriter。
缓冲流:
BufferedInputStream, BufferedOuputStream
BufferedReader, BufferedWriter
转换流(用于将字节流转换为字符流):
InputStreamReader,OutputStreamWriter
对象流(用于对象序列化和反序列化):
ObjectInputStream,ObjectOutputStream
打印流:
PrintStream,PrintWriter
推回输入流:
PushbackInputStream,PushbackReader
流的串行化:
SequenceInputStream
3.其它
①Java的标准输入输出分别通过System.in和System.out来代表,在默认情况下它们分别代表键盘和显示器。
②JVM读写其它进程的数据:
Process p = Runtime.getRuntime().exec(xxx);
//获取子进程的错误流
InputStream error=p.getErrorStream();
//获取子进程的输入流
InputStream in=p.getInputStream();
//获取子进程的输出流
OutputStream out=p.getOutputStream();
这里的输入流和输出流容易混淆。如果让子进程读取程序中的数据,则应该使用输出流。要站在Java程序的角度来看问题,子进程读取Java程序的数据,就是让Java程序把数据输出到子进程中(就像把数据输出到文件中一样,只是现在由子进程代替了文件节点),所以应该使用输出流。
④流的关闭
在使用处理流包装了底层节点流之后,关闭IO时,只需要关闭上层的处理流即可。系统会自动关闭被处理流包装的节点流。
⑤文本文件的读写
文本文件的输出
PrintWriter out = new PrintWriter("employee.txt", "UTF-8");
等价于
PrintWriter out = new PrintWriter( new FileOutputStream("employee.txt"), "UTF-8");
文本文件的读取:
//短文本的读取
String content = new String(Files.readAllBytes(path), charset);
//按照行的形式读取
List<String> lines = Files.readAllLines(path, charset);
//(传统方式)读取文件写法,一行行的读
InputStream inputStream = . . .;
try (BufferedReader in = new BufferedReader(new InputStreamReader(inputStream)))
{
String line;
while ((line = in.readLine()) != null) {
do something with line
}
}
//(新方式)大文本的读取
try (Stream<String> lines = Files.lines(path, charset)) {
...
}