字符流

字符流,Writer,Reader

当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。

字符流,只能操作文本文件,不能操作图片,视频等非文本文件

Reader:字符输入流

是字符输入流的最顶层的父类,定义了一些共性的成员方法,是一个抽象类

共性的成员方法:

int read():读取单个字符并返回

int read(char[] cbuf):一次读取多个字符,将字符读入数组

void close():关闭该流并释放与之关联的所有资源

FileReader:文件字符输入流

java.io.FileReader extends InputStreamReader extends Reader

作用: 把硬盘文件中的数据以字符的方式读取到内存中

构造方法:

FileReader(String fileName)

FileReader(File file)

字符输入流的使用步骤:

  • 创建FileReader对象,构造方法中绑定要读取的数据源
  • 使用FileReader对象中的方法read读取文件
  • 释放资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//1.创建FileReader对象,构造方法中绑定要读取的数据源
FileReader fr = new FileReader("c.txt");
//2.使用FileReader对象中的方法read读取文件
//int read() 读取单个字符并返回。
int len = 0;
while((len = fr.read())!=-1){
System.out.print((char)len);
}
//3.释放资源
fr.close();


FileReader fr2 = new FileReader("c.txt");
//int read(char[] cbuf)一次读取多个字符,将字符读入数组。
char[] cs = new char[1024];//存储读取到的多个字符
int len2 = 0;//记录的是每次读取的有效字符个数
while((len2 = fr2.read(cs))!=-1){
/*
String类的构造方法
String(char[] value) 把字符数组转换为字符串
String(char[] value, int offset, int count) 把字符数组的一部分转换为字符串 offset数组的开始索引 count转换的个数
*/
System.out.println(new String(cs,0,len2));
}
fr2.close();

Writer:字符输出流

是所有字符输出流的最顶层的父类,是一个抽象类

共性的成员方法:

void write(int c) :写入单个字符。

**void write(char[] cbuf)**:写入字符数组。

abstract void write(char[] cbuf, int off, int len):写入字符数组的某一部分,off数组的开始索引,len写的字符个数。

void write(String str):写入字符串

void write(String str, int off, int len): 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。

void flush():刷新该流的缓冲。

void close(): 关闭此流,但要先刷新它。

FileWriter:文件字符输出流

java.io.FileWriter extends OutputStreamWriter extends Writer

作用:把内存中字符数据写入到文件中

构造方法:

FileWriter(File file):根据给定的 File 对象构造一个 FileWriter 对象

FileWriter(String fileName): 根据给定的文件名构造一个 FileWriter 对象

字符输出流的使用步骤(重点):

  • 创建FileWriter对象,构造方法中绑定要写入数据的目的地
  • 使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)
  • 使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
  • 释放资源(会先把内存缓冲区中的数据刷新到文件中)
1
2
3
4
5
6
7
8
// 使用文件名称创建流对象
FileWriter fw = new FileWriter("fw.txt");
// 写出数据
fw.write(97); // 写出第1个字符
fw.write('b'); // 写出第2个字符
fw.write('C'); // 写出第3个字符
fw.write(30000); // 写出第4个字符,中文编码表中30000对应一个汉字。
fw.close();

输出结果:abC田

注意:

关闭资源时,与FileOutputStream不同,如果不关闭,数据只是保存到缓冲区,并未保存到文件。

虽然参数为int类型四个字节,但是只会保留一个字符的信息写出

void write(char[] cbuf):写入字符数组

abstract void write(char[] cbuf, int off, int len):写入字符数组的某一部分,off数组的开始索引,len写的字符个数

void write(String str):写入字符串

void write(String str, int off, int len): 写入字符串的某一部分,off字符串的开始索引,len写的字符个数

1
2
3
4
5
6
7
8
9
10
FileWriter fw = new FileWriter("f.txt");
char[] cs = {'a','b','c','d','e'};
fw.write(cs);//abcde

fw.write(cs,1,3);//bcd

fw.write("传智播客");//传智播客

fw.write("黑马程序员",2,3);//程序员
fw.close();

关闭和刷新

flush:刷新缓冲区,流对象可以继续使用

close: 先刷新缓冲区,然后通知系统释放资源,流对象不可以再被使用了

1
2
3
4
5
6
7
8
9
10
11
12
// 使用文件名称创建流对象
FileWriter fw = new FileWriter("fw.txt");
// 写出数据,通过flush
fw.write('刷'); // 写出第1个字符
fw.flush();
fw.write('新'); // 继续写出第2个字符,写出成功
fw.flush();
// 写出数据,通过close
fw.write('关'); // 写出第1个字符
fw.close();
fw.write('闭'); // 继续写出第2个字符,【报错】java.io.IOException: Stream closed
fw.close();

转换流

转换流(InputStreamReaderOutputStreamWriter)是 Java I/O 中的一种字符流,用于将字节流转换为字符流,以便更方便地处理字符数据。它们提供了字符和字节之间的桥梁,支持指定字符集进行编码和解码。

注意:在 Java 11 及以后的版本中,推荐直接使用 FileReaderFileWriter,它们底层已经集成了字符集的处理。

编码引出的问题

在IDEA中,使用FileReader读取项目中的文本文件。由于IDEA的设置,都是默认的UTF-8编码,所以没有任何问题。但是,当读取Windows系统中创建的文本文件时,由于Windows系统的默认是GBK编码,就会出现乱码。

1
2
3
4
5
6
7
8
9
10
public class ReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fileReader = new FileReader("E:\\File_GBK.txt");
int read;
while ((read = fileReader.read()) != -1) {
System.out.print((char)read);
}
fileReader.close();
}
}

InputStreamReader

转换流java.io.InputStreamReader,是Reader的子类,是从字节流到字符流的桥梁。它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。

构造方法

InputStreamReader(InputStream in): 创建一个使用默认字符集的字符流。

InputStreamReader(InputStream in, String charsetName): 创建一个指定字符集的字符流。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class ReaderDemo2 {
public static void main(String[] args) throws IOException {
// 定义文件路径,文件为gbk编码
String FileName = "E:\\file_gbk.txt";
// 创建流对象,默认UTF8编码
InputStreamReader isr = new InputStreamReader(new FileInputStream(FileName));

// 创建流对象,指定GBK编码
InputStreamReader isr2 = new InputStreamReader(new FileInputStream(FileName) , "GBK");


// 定义变量,保存字符
int len;
// 使用默认编码字符流读取,乱码
while ((len = isr.read()) != -1) {
System.out.print((char)len); // ��Һ�
}
isr.close();

// 使用指定编码字符流读取,正常解析
while ((len = isr2.read()) != -1) {
System.out.print((char)len); // 大家好
}
isr2.close();
}
}

OutputStreamWriter

转换流java.io.OutputStreamWriter,是Writer的子类,是从字符流到字节流的桥梁。使用指定的字符集将字符编码为字节,它的字符集可以由名称指定,也可以接受平台的默认字符集。

构造方法

OutputStreamWriter(OutputStream in): 创建一个使用默认字符集的字符流。

OutputStreamWriter(OutputStream in, String charsetName): 创建一个指定字符集的字符流。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class OutputDemo {
public static void main(String[] args) throws IOException {
// 定义文件路径
String FileName = "E:\\out.txt";
// 创建流对象,默认UTF8编码
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(FileName));
// 写出数据
osw.write("你好"); // 保存为6个字节
osw.close();

// 定义文件路径
String FileName2 = "E:\\out2.txt";
// 创建流对象,指定GBK编码
OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream(FileName2),"GBK");
// 写出数据
osw2.write("你好"); // 保存为4个字节
osw2.close();
}
}

字符流
http://example.com/2023/06/26/Java/JavaIO/3. 字符流,Writer,Reader/
作者
PALE13
发布于
2023年6月26日
许可协议