JAVA-编程基础-11-04-javaIO字符流
- IT业界
- 2025-08-16 02:27:02

Lison <dreamlison@163 >, v1.0.0, 2023.05.07
JAVA-编程基础-11-04-java IO 字符流 文章目录 JAVA-编程基础-11-04-java IO 字符流字符流Reader 和 Writer字符输入流(Reader)**FileReader构造方法****FileReader读取字符数据** 字符输出流(Writer)FileWriter 构造方法FileWriter写入数据 字符流Reader 和 Writer字符流 Reader 和 Writer 的故事要从它们的类关系图开始,来看图。
字符流是一种用于读取和写入字符数据的输入输出流。与字节流不同,字符流以字符为单位读取和写入数据,而不是以字节为单位。常用来处理文本信息。
如果用字节流直接读取中文,可能会遇到乱码问题,见下例:
//FileInputStream为操作文件的字符输入流 FileInputStream inputStream = new FileInputStream("files/a.txt");//内容为“Lison 勤学苦练 !!” int len; while ((len=inputStream.read())!=-1){ System.out.print((char)len); }运行结果:
运行结果:Lison 勤å¦è‹¦ç»之所以出现乱码是因为在字节流中,一个字符通常由多个字节组成,而不同的字符编码使用的字节数不同。如果我们使用了错误的字符编码,或者在读取和写入数据时没有正确处理字符编码的转换,就会导致读取出来的中文字符出现乱码。
例如,当我们使用默认的字符编码(见上例)读取一个包含中文字符的文本文件时,就会出现乱码。因为默认的字符编码通常是 ASCII 编码,它只能表示英文字符,而不能正确地解析中文字符。
那使用字节流该如何正确地读出中文呢?见下例。
//FileInputStream为操作文件的字符输入流//内容为“Lison 勤学苦练 !!” try (FileInputStream inputStream = new FileInputStream("files/a.txt");){ byte[] bytes = new byte[1024]; int len; while ((len = inputStream.read(bytes)) != -1) { System.out.print(new String(bytes, 0, len)); } } catch (Exception e) { e.printStackTrace(); } 运行结果: Lison 勤学苦练为什么这种方式就可以呢?
因为我们拿 String 类进行了解码,查看new String(byte bytes[], int offset, int length)的源码就可以发现,该构造方法有解码功能
public String(byte bytes[], int offset, int length) { checkBounds(bytes, offset, length); this.value = StringCoding.decode(bytes, offset, length); }继续追看 StringCoding.decode() 方法调用的 defaultCharset() 方法,会发现默认编码是UTF-8,代码如下
static char[] decode(byte[] ba, int off, int len) { String csn = Charset.defaultCharset().name(); try { // use charset name decode() variant which provides caching. return decode(csn, ba, off, len); } catch (UnsupportedEncodingException x) { warnUnsupportedCharset(csn); } } public static Charset defaultCharset() { if (defaultCharset == null) { synchronized (Charset.class) { String csn = AccessController.doPrivileged( new GetPropertyAction("file.encoding")); Charset cs = lookup(csn); if (cs != null) defaultCharset = cs; else defaultCharset = forName("UTF-8"); } } return defaultCharset; }在 Java 中,常用的字符编码有 ASCII、ISO-8859-1、UTF-8、UTF-16 等。其中,ASCII 和 ISO-8859-1 只能表示部分字符,而 UTF-8 和 UTF-16 可以表示所有的 Unicode 字符,包括中文字符。
当我们使用 new String(byte bytes[], int offset, int length) 将字节流转换为字符串时,Java 会根据 UTF-8 的规则将每 3 个字节解码为一个中文字符,从而正确地解码出中文。
尽管字节流也有办法解决乱码问题,但不够直接,于是就有了字符流,专门用于处理文本文件(音频、图片、视频等为非文本文件)。
从另一角度来说:字符流 = 字节流 + 编码表
字符输入流(Reader)java.io.Reader是字符输入流的超类(父类),它定义了字符输入流的一些共性方法:
1、close():关闭此流并释放与此流相关的系统资源。2、read():从输入流读取一个字符。3、read(char[] cbuf):从输入流中读取一些字符,并将它们存储到字符数组 cbuf中FileReader 是 Reader 的子类,用于从文件中读取字符数据。它的主要特点如下:
可以通过构造方法指定要读取的文件路径。每次可以读取一个或多个字符。可以读取 Unicode 字符集中的字符,通过指定字符编码来实现字符集的转换。 FileReader构造方法 1、FileReader(File file):创建一个新的 FileReader,参数为File对象。2、FileReader(String fileName):创建一个新的 FileReader,参数为文件名。代码示例如下:
// 使用File对象创建流对象 File file = new File("files/a.txt"); FileReader fr = new FileReader(file); // 使用文件名称创建流对象 FileReader fr = new FileReader("files/b.txt"); FileReader读取字符数据①、读取字符:read方法,每次可以读取一个字符,返回读取的字符(转为 int 类型),当读取到文件末尾时,返回-1。代码示例如下:
// 使用文件名称创建流对象 FileReader fr = new FileReader("files/abc.txt"); // 定义变量,保存数据 int b; // 循环读取 while ((b = fr.read())!=-1) { System.out.println((char)b); } // 关闭资源 fr.close();②、读取指定长度的字符:read(char[] cbuf, int off, int len),并将其存储到字符数组中。其中,cbuf 表示存储读取结果的字符数组,off 表示存储结果的起始位置,len 表示要读取的字符数。代码示例如下:
File textFile = new File("files/abc.txt"); // 给一个 FileReader 的示例 // try-with-resources FileReader try(FileReader reader = new FileReader(textFile);) { // read(char[] cbuf) char[] buffer = new char[1024]; int len; while ((len = reader.read(buffer, 0, buffer.length)) != -1) { System.out.print(new String(buffer, 0, len)); } }catch (Exception e){ }使用 FileReader 从文件中读取字符数据,并将其存储到一个大小为 1024 的字符数组中。每次读取 len 个字符,然后使用 String 构造方法将其转换为字符串并输出。
FileReader 实现了 AutoCloseable 接口,因此可以使用 try-with-resources语句自动关闭资源,避免了手动关闭资源的繁琐操作。
字符输出流(Writer)java.io.Writer 是字符输出流类的超类(父类),可以将指定的字符信息写入到目的地,来看它定义的一些共性方法:
1、write(int c) 写入单个字符。2、write(char[] cbuf) 写入字符数组。3、write(char[] cbuf, int off, int len) 写入字符数组的一部分,off为开始索引,len为字符个数。4、write(String str) 写入字符串。5、write(String str, int off, int len) 写入字符串的某一部分,off 指定要写入的子串在 str 中的起始位置,len 指定要写入的子串的长度。6、flush() 刷新该流的缓冲。7、close() 关闭此流,但要先刷新它。java.io.FileWriter 类是 Writer 的子类,用来将字符写入到文件。
FileWriter 构造方法 FileWriter(File file): 创建一个新的 FileWriter,参数为要读取的File对象。FileWriter(String fileName): 创建一个新的 FileWriter,参数为要读取的文件的名称。 // 第一种:使用File对象创建流对象 File file = new File("files/a.txt"); FileWriter fw = new FileWriter(file); // 第二种:使用文件名称创建流对象 FileWriter fw = new FileWriter("files/b.txt"); FileWriter写入数据①、写入字符:write(int b) 方法,每次可以写出一个字符,代码示例如下:
FileWriter fw = null; try { fw = new FileWriter("output.txt"); fw.write(72); // 写入字符'H'的ASCII码 fw.write(101); // 写入字符'e'的ASCII码 fw.write(108); // 写入字符'l'的ASCII码 fw.write(108); // 写入字符'l'的ASCII码 fw.write(111); // 写入字符'o'的ASCII码 } catch (IOException e) { e.printStackTrace(); } finally { try { if (fw != null) { fw.close(); } } catch (IOException e) { e.printStackTrace(); } }在这个示例代码中,首先创建一个 FileWriter 对象 fw,并指定要写入的文件路径 “output.txt”。然后使用 fw.write() 方法将字节写入文件中,这里分别写入字符’H’、‘e’、‘l’、‘l’、'o’的 ASCII 码。最后在 finally 块中关闭 FileWriter 对象,释放资源。
需要注意的是,使用 write(int b) 方法写入的是一个字节,而不是一个字符。如果需要写入字符,可以使用 write(char cbuf[]) 或 write(String str) 方法。
写入字符数组:write(char[] cbuf) 方法,将指定字符数组写入输出流。代码示例如下:
FileWriter fw = null; try { fw = new FileWriter("output.txt"); char[] chars = {'H', 'e', 'l', 'l', 'o'}; fw.write(chars); // 将字符数组写入文件 } catch (IOException e) { e.printStackTrace(); } finally { try { if (fw != null) { fw.close(); } } catch (IOException e) { e.printStackTrace(); } }JAVA-编程基础-11-04-javaIO字符流由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“JAVA-编程基础-11-04-javaIO字符流”