Java 中 的 IO 操作就是对字型节或字符型数据的读写。
一、IO 分类
1.按流的方向分类
- 输入流(InputStream、Reader):只能进行读操作。
- 输出流(OutputStream、Writer):只能进行写操作。
2.按流的类型分类
- 字节流(InputStream、OutputStream):以字节(8bit)为单位,可以处理任何类型的数据。
- 字符流(Reader、Writer):以字符为单位,字节流读取时,根据码表映射成字符。一次可能读多个字节。只能处理字符类型的数据。
二、IO 类使用
1.基类(抽象类:InputStream/Reader,OutputStream/Writer。其它 IO 操作类都是基于这些抽象类)
InputStream(输入字符流)
- int read():从输入流中读取单个字节。返回所读取的字节数据(字节数据可直接转换为int类型)。
- int read(byte[] b):从输入流中最多读取 b.length 个字节的数据,并将其存储在字节数组 b 中。返回实际读取的字节数。
- int read(byte[] b, int off, int len);:从输入流中最多读取 len 个字节的数据,并将其存储在数组 b 中,放入数组 b 中时,并不是从数组起点开始,而是从 off 位置开始。返回实际读取的字节数。
- int available():返回流中尚未读取的字节的数。
- long skip(long n):跳过 n 个字节不读。返回实际跳过的字节数。
- void mark(int readlimit):标记流的当前读取位置。
- void reset():使流的读取位置恢复到最后一次调用 mark() 方法所标记的位置。
- boolean markSupported():测试当前流是否支持 mark()/reset() 组合。
- void close():关闭流,GC 无法释放 IO 资源,需手动关闭。
OutputStream(输出字符流)
- void write(int b):往流中写一个字节 b。
- void write(byte b[]):往流中写一个字节数组 b。
- void write(byte b[], int off, int len):把字节数组 b 中从下标 off 开始,长度为 len 的字节写入到流中。
- void flush():刷新流,输出所有被缓存的字节。某些流支持缓存功能,该方法将把缓存中所有内容强制输出到流中。
- close()
Reader(输入字节流)
- int read():从输入流中读取单个字符,返回所读取的字符数据(字符数据可直接转换为int类型)。
- int read(char[] b)
- int read(char[] b, int off, int len)
- int read(java.nio.CharBuffer target)
- boolean ready():判断此流是否可以读取
- long skip(long n)
- void mark(int readlimit)
- void reset()
- boolean markSupported()
- void close()
Writer(输出字节流)
- void write(int c):将(字节/字符)输出到输出流中。
- void write(char cbuf[]):将(字节数组/字符数组)中的数据输出到指定输出流中。
- void write(char cbuf[], int off, int len):将(字节数组/字符数组)中从 off 位置开始,长度为 len 的(字节/字符)输出到此 Writer。
- void write(String str):将 str 字符串里包含的字符输出到此 Writer。
- void write(String str, int off, int len):将 str 字符串里面从 off 位置开始,长度为 len 的字符输出到此 Writer。
- Writer append(char c):将指定的字符追加到此 Writer。
- Writer append(CharSequence csq)
- Writer append(CharSequence csq, int start, int end)
- void flush()
- void close()
2.实现类
基于文件(FileInputStream/FileReader ,FileOutputStream/FileWriter)
// 实现了 AutoCloseable 写在 try() 中可自动关闭流try (FileInputStream fis = new FileInputStream("D:\\tmp\\123.txt")) { // 字节数组 byte[] b = new byte[1024]; // 用于保存的实际字节数 int hasRead = 0; while ((hasRead = fis.read(b)) > 0) { System.out.print(new String(b, 0, hasRead, "UTF-8")); }} catch (FileNotFoundException e) { e.printStackTrace();} catch (IOException e) { e.printStackTrace();}try (FileReader fr = new FileReader("D:\\tmp\\123.txt")) { // 字符数组 char[] b = new char[1024]; int hasRead = 0; while ((hasRead = fr.read(b)) > 0) { System.out.print(new String(b, 0, hasRead)); }} catch (IOException e) { e.printStackTrace();}// 复制文件try (FileInputStream fis = new FileInputStream("D:\\tmp\\123.txt"); FileOutputStream fos = new FileOutputStream("D:\\tmp\\456.txt")) { byte[] b = new byte[1024]; int hasRead = 0; while ((hasRead = fis.read(b)) > 0) { fos.write(b, 0, hasRead); }} catch (FileNotFoundException e) { e.printStackTrace();} catch (IOException e) { e.printStackTrace();}// 复制文件try (FileReader fr = new FileReader("D:\\tmp\\123.txt"); FileWriter fw = new FileWriter("D:\\tmp\\456.txt")) { char[] b = new char[1024]; int hasRead = 0; while ((hasRead = fr.read(b)) > 0) { fw.write(b, 0, hasRead); }} catch (FileNotFoundException e) { e.printStackTrace();} catch (IOException e) { e.printStackTrace();}
缓存流(BufferedInputStream/BufferedReader,BufferedOutputStream/BufferedWriter)。支持 mark
try (FileInputStream fis = new FileInputStream("D:\\tmp\\123.txt"); FileOutputStream fos = new FileOutputStream("D:\\tmp\\456.txt"); BufferedInputStream bis = new BufferedInputStream(fis); BufferedOutputStream bos = new BufferedOutputStream(fos)) { byte[] b = new byte[1024]; int hasRead = 0; while ((hasRead = bis.read(b)) > 0) { bos.write(b, 0, hasRead); }} catch (FileNotFoundException e) { e.printStackTrace();} catch (IOException e) { e.printStackTrace();}try (FileReader fr = new FileReader("D:\\tmp\\123.txt"); FileWriter fw = new FileWriter("D:\\tmp\\456.txt"); BufferedReader br = new BufferedReader(fr); BufferedWriter bw = new BufferedWriter(fw)) { char[] b = new char[1024]; int hasRead = 0; while ((hasRead = br.read(b)) > 0) { bw.write(b, 0, hasRead); }} catch (FileNotFoundException e) { e.printStackTrace();} catch (IOException e) { e.printStackTrace();}
转换流(InputStreamReader/OutputStreamWriter)。将字节流转为字符流
try (FileInputStream fis = new FileInputStream("D:\\tmp\\123.txt"); FileOutputStream fos = new FileOutputStream("D:\\tmp\\456.txt"); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos))) { char[] b = new char[1024]; int hasRead = 0; while ((hasRead = br.read(b)) > 0) { bw.write(b, 0, hasRead); }} catch (FileNotFoundException e) { e.printStackTrace();} catch (IOException e) { e.printStackTrace();}
对象流(ObjectInputStream/ObjectOutputStream)。用于序列化
三、IO 分类表
Java 输入/输出流体系中常用的流的分类表
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
---|---|---|---|---|
抽象基类 | InputStream | OutputStream | Reader | Writer |
访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
访问管道 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
访问字符串 | StringReader | StringWriter | ||
缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
转换流 | InputStreamReader | OutputStreamWriter | ||
对象流 | ObjectInputStream | ObjectOutputStream | ||
抽象基类 | FilterInputStream | FilterOutputStream | FilterReader | FilterWriter |
打印流 | PrintStream | PrintWriter | ||
推回输入流 | PushbackInputStream | PushbackReader | ||
特殊流 | DataInputStream | DataOutputStream |
表中 粗体 字所标出的类代表节点流,必须直接与指定的物理节点关联。斜体字加下划线 标出的类代表抽象基类,无法直接创建实例。
字节流的输入与输出对应图
字符流的输入与输出对应图