Reader、Writer
IO 流体系图
Reader
Reader 是输 ⼊字符流的 ⽗类,它是 ⼀个抽象类, 部分库不推荐使 ⽤ Reader/Writer。
常见方法
1//⼀个字符⼀个字符的读,只能⽤来操作⽂本(不能写图⽚ ⾳频 视频)
2int read()
3
4//从输⼊字符流中读取⼀定数量的字符,并将其存储在缓冲区数组cbuf中, 返回实际读取的字符 数,如果已经到达流末尾⽽没有可⽤的字节,则返回-1
5int read(char cbuf[])
6
7//关闭输⼊流并释放与该流关联的系统资源
8void close() throws IOException
FileReader
用来读取字符 ⽂件的实现类。
1/**
2 * 读取中⽂显示出来, java运⾏时采⽤utf16编码,多数汉字占2个字节,⼀个char就够,少数占4个字节,需要两个char来表示
3 */
4 @Test
5 public void readerCharArrayTesting() throws IOException {
6 String filePath = "C:\\Users\\Ryzen-7-3800X\\Pictures\\Camera Roll\\test\\1\\1.txt";
7 File file = new File(filePath);
8 FileReader input = new FileReader(file);
9
10 int size;
11 char[] ch = new char[1024];
12
13 while ((size = input.read(ch)) != -1){
14 System.out.print(new String(ch,0,size));
15 }
16 input.close();
17 }
Writer
Writer 是输出字符流的 ⽗类,它是 ⼀个抽象类。
1//直接将int型数据作为参数的话,是不会写⼊数字的,⽽是现将数字按照ascll码表转换为 相应的字符,然后写⼊
2public void write(int c) throws IOException
3
4//要想实现数字和中⽂的写⼊,必须要⽤String为参数的Write
5public void write(String str) throws IOException
6
7//将cbuf字符数组的⼀部分写⼊到流中,但能不能写len个字符取决于cbuf中是否有那么多
8public abstract void write(char cbuf[], int off, int len) throws IOException;
9
10//write是写到缓冲区中,可以认为是内存中,当缓冲区满时系统会⾃动将缓冲区的内容写⼊ ⽂件,但是⼀般还有⼀部分有可能会留在内存这个缓冲区中, 所以需要调⽤flush空缓冲区数据。 对⽐BufferWriter需要实时查表,效率低,其实缓冲区IO的各个都有,只不过很⼩被忽 略,OutputStream都有flush⽅法,看⼦类是否有重写
11void flush() throws IOException
12
13//关闭输⼊流并释放与该流关联的系统资源
14void close() throws IOException
FileWriter
⽤来写出字符 ⽂件的实现类。
1//如果⽂件不存在,这会⾃动创建。如果⽂件存在,则会覆盖
2public FileWriter(String fileName) throws IOException
3
4//如果⽂件不存在,这会⾃动创建。如果⽂件存在,则会覆盖
5public FileWriter(File file) throws IOException
6
7//加⼊true参数,会实现对⽂件的续写,使⽤false则会实现对⽂件的覆盖
8public FileWriter(String fileName, boolean append) throws IOException
9
10//加⼊true参数,会实现对⽂件的续写,使⽤false则会实现对⽂件的覆盖
11public FileWriter(File file, boolean append) throws IOException
示例
1/**
2 * 传入int类型参数会查表 ASCII码 查表会消耗性能
3 * 传入string类型参数 不会查表,直接写入,没有多余的性能开销
4 * @throws IOException
5 */
6 @Test
7 public void writerTesting() throws IOException {
8 String filePath = "C:\\Users\\Ryzen-7-3800X\\Pictures\\Camera Roll\\test\\1\\2.txt";
9 FileWriter writer = new FileWriter(filePath);
10 //FileWriter writer = new FileWriter(filePath,true); //追加
11 //FileWriter writer = new FileWriter(filePath,false); //覆盖
12
13 writer.write(23567); //小
14 writer.write(28404); //滴
15 writer.write(35838); //课
16 writer.write(22530); //堂
17 writer.write("23567"); //23567
18 writer.flush();
19 writer.close();
20 }
BufferedReader
为了提 ⾼了单个字符读写的效率,进 ⾏字符批量的读写; 为了提 ⾼字符流读写的效率,引 ⼊了缓冲机制。
当 BufferedReader 在读取 ⽂本 ⽂件时,会先尽量从 ⽂件中读 ⼊字符数据并放满缓冲 区,⽽之后若使 ⽤ read()⽅法,会先从缓冲区中进 ⾏读取。如果缓冲区数据不 ⾜,才会再从 ⽂ 件中读取。
构造函数
1BufferedReader(Reader in)
2
3//创建⼀个使⽤指定⼤⼩输⼊缓冲区的缓冲字符输⼊流。
4BufferedReader(Reader in, int sz)
常用 API
1//判断此流是否已准备好被读取,依赖其他流,所以⼀般需要做判断
2boolean ready()
3
4//读取单个字符
5int read()
6
7//读取⼀部分字符到数组⾥⾯,从数组下标off处放置length⻓度的字符
8int read(char[] cbuf, int off, int len)
9
10//读取⼀整⾏⽂本⾏,返回⼀整⾏字符串,如果读到⾏尾了就返回null,注意返回的⼀⾏字符中不 包含换⾏符
11String readLine()
12
13//读取⼀整⾏⽂本⾏,返回⼀整⾏字符串,如果读到⾏尾了就返回null,注意返回的⼀⾏字符中不 包含换⾏符
14String readLine()
示例
1/**
2 * read()
3 * @throws IOException
4 */
5 @Test
6 public void bufferedWriterTesting() throws IOException {
7 String filePath = "C:\\Users\\Ryzen-7-3800X\\Pictures\\Camera Roll\\test\\1\\1.txt";
8 BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
9 if (!bufferedReader.ready()) {
10 System.out.println("文件流暂时无法读取");
11 return;
12 }
13
14 int size;
15 char[] cbuf = new char[1024];
16 while ((size = bufferedReader.read(cbuf, 0, cbuf.length)) != -1) {
17 System.out.println(new String(cbuf,0,size));
18 }
19 }
20
21 /**
22 * readLine()
23 * @throws IOException
24 */
25 @Test
26 public void bufferedWriterReadlineTesting() throws IOException {
27 String filePath = "C:\\Users\\Ryzen-7-3800X\\Pictures\\Camera Roll\\test\\1\\1.txt";
28 BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
29 if (!bufferedReader.ready()) {
30 System.out.println("文件流暂时无法读取");
31 return;
32 }
33
34 String str = "";
35 while ((str = bufferedReader.readLine()) != null) {
36 System.out.println(str);
37 }
38 bufferedReader.close();
39 }
BufferedWriter
写 ⼊的数据并不会先输出到 ⽬的地,⽽是先存储 ⾄缓冲区中。如果缓冲区中的数据满 了,才会 ⼀次对 ⽬的地进 ⾏写出。
构造函数
1BufferedWriter(Writer out)
2
3BufferedWriter(Writer out, int sz)
常用 API
1//写⼊⼀个字符
2void write(int c)
3
4//写⼊字符数组的⼀部分,通过off和len控制。
5void write(char[] cbuf, int off, int len)
6
7//写⼊字符串的⼀部分,通过off和len控制。
8void write(String s, int off, int len)
9
10//写如⼀个换⾏符合
11void newLine()
12
13//关闭输⼊流并释放与该流关联的系统资源
14void close()
15
16//write是写到缓冲区中,可以认为是内存中,当缓冲区满时系统会⾃动将缓冲区的内容 写⼊⽂件,但是⼀般还有⼀部分有可能会留在内存这个缓冲区中, 所以需要调⽤flush空缓 冲区数据。
17void flush()
示例
1@Test
2 public void BufferedWriterTest() throws IOException {
3 String filePath = "C:\\Users\\Ryzen-7-3800X\\Pictures\\Camera Roll\\test\\1\\2.txt";
4 BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
5
6 //写入一个字符
7 char ch = '你';
8 bufferedWriter.write(ch);
9
10 //写入一个字符数组
11 String strArray = "好!北京欢迎你!";
12 bufferedWriter.write(strArray.toCharArray(),0,strArray.length());
13
14 //写入一个换行符
15 bufferedWriter.newLine();
16
17 //写入一个字符串
18 String newStr = "哈哈哈!";
19 bufferedWriter.write(newStr);
20
21 //关闭资源
22 bufferedWriter.close();
23
24 //你好!北京欢迎你!
25 //哈哈哈!
26 }
InputStreamReader
计算机存储的单位是字节,从持久设备读取到程序中是解码,从程序写到持久设备中是编码 不管是编码还是解码,不同字符集编解码成 字符 需要不同的个数,因此字节流读取容易出错,⽐ 如乱码。
需要 ⼀个流,把字节流读取的字节进 ⾏缓冲后,在通过字符集解码成字符返回。
InputStreamReader(继承 Reader)
将字节流转换为字符流, 字节流通向字符流的桥梁,如果不指定字符集编码,则解码过程 将使 ⽤平台默认的字符编码,如:UTF-8
⽂本 ⽂件存储是 A 编码,然后如果以 B 编码进 ⾏读取则会乱码
构造函数
1//使⽤系统默认编码集
2public InputStreamReader(InputStream in)
3
4//指定指定编码集创建对象
5public InputStreamReader(InputStream in, String charsetName)
常用 API
1//读取单个字符
2int read()
3
4//读取⼀部分字符到数组⾥⾯,从数组下标off处放置length⻓度的字符
5int read(char[] cbuf, int off, int len)
6
7//将读取到的字符存到数组中,返回读取的字符数
8int read(char []cbuf)
9
10//关闭流释放资源
11void close()
示例
1@Test
2 public void inputStreamReadTesting() throws IOException {
3 String filePath = "C:\\Users\\Ryzen-7-3800X\\Pictures\\Camera Roll\\test\\1\\1.txt";
4 //读取字节流
5 InputStream inputStream = new FileInputStream(filePath);
6
7 //字节流向字符流转换: 转换之后变为InputStreamReader 属于 字符流
8 InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");//默认解码采用UTF-8
9
10 //字符流缓冲区对 InputStreamReader 进行包装,提高性能
11 BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
12
13 String line;
14
15 while ((line = bufferedReader.readLine()) != null) {
16 System.out.println(line);
17 }
18 inputStream.close();
19 bufferedReader.close();
20 }
OutputStreamWriter
将字符流转换为字节流(看源码解释), 字符流通向字节流的桥梁,如果不指定字符集编码,则编码过程将使 ⽤平台默认的字符编码,如:GBK
构造函数
1//使⽤系统默认编码集
2public OutputStreamWriter(OutputStream out)
3
4//指定指定编码集创建对象
5public OutputStreamWriter(OutputStream out, String charsetName)
常用 API
1//写⼊⼀个字符
2void write(int c)
3
4//写⼊字符数组的⼀部分,通过off和len控制。
5void write(char[] cbuf, int off, int len)
6
7//写⼊字符数组的⼀部分,通过off和len控制。
8void write(String s, int off, int len)
9
10//写如⼀个换⾏符合
11void newLine()
12
13//关闭输⼊流并释放与该流关联的系统资源
14void close()
15
16//write是写到缓冲区中,可以认为是内存中,当缓冲区满时系统会⾃动将缓冲区的内容 写⼊⽂件,但是⼀般还有⼀部分有可能会留在内存这个缓冲区中, 所以需要调⽤flush空缓 冲区数据。
17void flush()
示例
1@Test
2 public void outputStreamReadTesting() throws IOException {
3 String filePath = "C:\\Users\\Ryzen-7-3800X\\Pictures\\Camera Roll\\test\\1\\2.txt";
4
5 //写入字节流
6 OutputStream outputStream = new FileOutputStream(filePath);
7
8 //将写入字符流转成写入字节流
9 OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream,"UTF-8");//默认的编码是UTF-8
10
11 //采用Buffered包装写入字符流
12 BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
13
14 String str = "北京欢迎你! Welcome to Bei Jing! ";
15
16 bufferedWriter.write(str);
17 bufferedWriter.newLine();
18 bufferedWriter.write("哈哈哈!~");
19 bufferedWriter.flush();
20 bufferedWriter.close();
21
22 //北京欢迎你! Welcome to Bei Jing!
23 //哈哈哈!~
24 }