开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情
前言
当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。
一、字符流
字符流可以分为字符输入流FileReader和字符输出流FileWriter。
二、字符输入流FileReader
2.1 字符输入流抽象父类--Reader
java.io.Reader抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。
public int read()
:从输入流读取一个字符。\public int read(char[] cbuf)
:从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。public void close()
:关闭此流并释放与此流相关联的任何系统资源。\
2.2 文件字符输入流FileReader
2.2.1 构造方法
java.io.FileReader类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
- 字符编码:字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。idea中UTF-8\
- 字节缓冲区:一个字节数组,用来临时存储字节数据。
FileReader(File file)
:创建一个新的 FileReader ,给定要读取的File对象。\FileReader(String fileName)
:创建一个新的 FileReader ,给定要读取的文件的名称。
当你创建一个流对象时,必须传入一个文件路径。类似于FileInputStream 。【传入的文件不存在,出现异常:FileNotFoundException】
public class Test { public static void main(String[] args) throws FileNotFoundException { // 创建File对象 File file = new File("day10_io/src/is.txt"); FileReader fr = new FileReader(file); System.out.println(fr); // 文件路径的字符串构建字符输入流 FileReader fileReader = new FileReader("day10_io/src/is.txt"); // 若文件不存在,异常! System.out.println(fileReader); } }
2.2.2 读取字符数据
/* 字符输入流FileReader读单个字符数据: int read() 读一个字符 */ public class Test { public static void main(String[] args) throws IOException { // 文件路径的字符串构建字符输入流 FileReader fr = new FileReader("day10_io/src/is.txt"); int r; while ((r = fr.read()) != -1) { System.out.println((char) r); } // 关闭资源 fr.close(); } }
② 使用字符数组读取:read(char[] cbuf),每次读取b的长度个字符到数组中,返回读取到的有效字符个数,读取到末尾时,返回-1
/* 字符输入流FileReader读字符数组数据: int read•(char[] cbuf) 将字符读入数组。 */ public class Test { public static void main(String[] args) throws IOException { // 文件路径的字符串构建字符输入流 FileReader fr = new FileReader("day10_io/src/is.txt"); // 掘金 // 定义字符数组 char[] chars = new char[2]; // 读取到字符数组中有效的字符数据的个数 int len; while ((len = fr.read(chars)) != -1) { // 包含了无效的数据! System.out.println(new String(chars)); } // 关闭资源 fr.close(); } }
获得有效字符改进:
/* 字符输入流FileReader读字符数组数据: int read•(char[] cbuf) 将字符读入数组。 */ public class Test { public static void main(String[] args) throws IOException { // 文件路径的字符串构建字符输入流 FileReader fr = new FileReader("day10_io/src/is.txt"); // 定义字符数组 char[] chars = new char[2]; // 读取到字符数组中有效的字符数据的个数 int len; while ((len = fr.read(chars)) != -1) { // 每次都是从数组的0索引位置到你读取到数组中有效长度的数据来构建字符串数据 System.out.println(new String(chars, 0, len)); } // 关闭资源 fr.close(); } }
三、字符输出流FileWriter
3.1 字符输出流Writer--抽象父类
java.io.Writer抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。
public void write(int c)
:// 写出一个字符。\public void write(char[] cbuf)
:// 将 b.length字符从指定的字符数组写出此输出流。\public abstract void write(char[] b, int off, int len)
:// 从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。\public void write(String str)
:// 写出一个字符串。public abstract void flush()
:// 刷新此输出流并强制任何缓冲的输出字符被写出。\public abstract void close()
:// 关闭此输出流并释放与此流相关联的任何系统资源。\
3.2 文件字符输出流FileWriter
3.2.1 文件字符输出流FileWriter--构造方法
java.io.FileWriter类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
FileWriter(File file)
:创建一个新的 FileWriter,给定要读取的File对象。\FileWriter(String fileName)
:创建一个新的 FileWriter,给定要读取的文件的名称。
当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream。
/* 字符输出流FileWriter的构造方法: FileWriter(File file): // 创建一个新的 FileWriter,给定要读取的File对象。 FileWriter(String fileName): // 创建一个新的 FileWriter,给定要读取的文件的名称。 注意:文件路径字符串构建FileWriter对象时,若路径中的文件不存在,不会报错,它会自动创建! */ public class Test { public static void main(String[] args) throws IOException { // 创建File对象 File file = new File("day10_io/src/fw.txt"); FileWriter fw = new FileWriter(file); System.out.println(fw); // 路径文件字符串构建FileWriter对象 FileWriter fw1 = new FileWriter("day10_io/src/fw1.txt"); System.out.println(fw1); } }
3.2.2文件字符输出流FileWriter--写出字符数据
写出字符:write(int b) 方法,每次可以写出一个字符数据 [97,b,c,30000]
/* FileWriter写出单个字符数据 【97,b,c,30000】 */ public class Test { public static void main(String[] args) throws IOException { // 创建对象 FileWriter fw = new FileWriter("day10_io/src/fw.txt"); // 写出单个字符数据 fw.write(97); fw.write('b'); fw.write('c'); fw.write(22269); // 释放资源 fw.close(); // 没有这行代码,那么数据不会到文件中!(还在内存的缓冲区!) } }
关闭和刷新
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要flush 方法了。
flush :// 刷新缓冲区,流对象可以继续使用。
close :// 关闭流,释放系统资源。关闭前会刷新缓冲区。
public class Test { public static void main(String[] args) throws IOException { // 创建对象 FileWriter fw = new FileWriter("day10_io/src/fw.txt"); // 写出单个字符数据 fw.write(97); fw.write('b'); fw.write('c'); fw.write(22269); // 先刷新内存中缓冲区的数据,然后关闭!后面不能再使用这个流对象,否则报错!Stream closed //fw.close(); // 只刷新缓冲区数据,不关闭流!后面可以继续使用流对象! fw.flush(); fw.write(100); fw.flush(); } }
写出字符数组 :write(char[] cbuf) 和 write(char[] cbuf, int off, int len) ,每次可以写出字符数组中的数据
/* FileWriter写出字符数组数据 void write•(char[] cbuf) 写入一个字符数组。 */ public class Test { public static void main(String[] args) throws IOException { // 创建对象 FileWriter fw = new FileWriter("day10_io/src/fw.txt"); // 创建字符数组 char[] chars = {'a', 'b', 'c', 'd'}; // 写出字符数组数据 fw.write(chars); // abcd // 释放资源! fw.close(); } }
/* FileWriter写出字符数组指定数据 void write•(char[] cbuf, int off, int len) 写入字符数组的一部分。 */ public class Test { public static void main(String[] args) throws IOException { // 创建对象 FileWriter fw = new FileWriter("day10_io/src/fw.txt"); // 创建字符数组 char[] chars = {'a', 'b', 'c', 'd'}; // 写出字符数组数据 fw.write(chars, 2, 2); // cd // 释放资源! fw.close(); } }
3.2.3文件字符输出流FileWriter--写出字符串
write(String str) 和 write(String str, int off, int len) ,每次可以写出字符串中的数据
/* FileWriter写出字符串数据,以及字符串指定数据 void write•(String str) 写一个字符串 void write•(String str, int off, int len) 写一个字符串的一部分。 */ public class Test { public static void main(String[] args) throws IOException { // 创建对象 FileWriter fw = new FileWriter("day10_io/src/fw.txt"); // 直接写出字符串数据 fw.write("掘金!"); // 已经具备续写能力! fw.write("666么么哒!", 0, 3); // 释放资源! fw.close(); } }
3.2.3 文件字符输出流FileWriter--续写和换行
操作类似于FileOutputStream,在构造方法后面加一个boolean类型的参数,取值为true即可!
/* FileWriter写出字符串数据,以及字符串指定数据 void write•(String str) 写一个字符串 void write•(String str, int off, int len) 写一个字符串的一部分。 */ public class Test { public static void main(String[] args) throws IOException { // 创建对象 FileWriter fw = new FileWriter("day10_io/src/fw.txt", true); // 直接写出字符串数据 fw.write("rn"); fw.write("黑马程序员!"); fw.write("rn"); // 已经具备续写能力! fw.write("666么么哒!", 0, 3); // 释放资源! fw.close(); } }
后记
喜欢我的文章的朋友点点喜欢、收藏,也欢迎朋友们评论区留下你的意见和建议,恕毅在此拜谢!