一, IO 流的分类
A, 按照操作的对象不同可分为字节流与字符流
B, 按照流的方向不同可分为输入 (指从外部存储设备拿文件到内存) 流也叫读与输出 (指从内存把文件写入到外部存储设备) 流也叫写
注: 字节流可以操作任何类型的文件, 字符流是后来才出现的, 主要用来操作字符类的文件; 字符流的出现源于编码表的问题, 一开始计算机内使用 ANSII 编码, 后来每种语言都有了自己的编码方式即编码表, 为了统一这些编码信息国际标准化组织便产生了 Unicode 编码信息表来把世界各国的语言都包括在内, 此编码表采用两个字节即 16 位来存储每一个字符, java 内置的编码表便是 Unicode 编码; 字符流是当读取文件的时候, 以字节的形式读取后, 查询编码表看具体使用哪种编码方式, 查到以后再进行文件的输出, 所以字符流是字节流 + 查编码表的封装形式.
二, 流的顶层基类
所有流的操作无非两种形式: 读与写; 所以 Java 便所这两种操作形式抽取出了字节流与字符流的两种顶层的基类
字节流的顶层基类: InputStream 与 OutputStream
字符流的顶层基类: Read 与 Write
三, 字符流 FileWriter
- public static void function_demo1() throws IOException {
- // 创建字符写入流对象, 接收一个要写入的文件路径对象, 此文件若不存在则新创建一个文件, 若已存在则覆盖的文件
- FileWriter fw = new FileWriter("demo1.txt");
- fw.write("abcdefg");// 把内容写入缓冲区
- fw.flush();// 从缓冲区把内容刷入文件中
- fw.close();// 关闭流
- }
注: 以上代码中 fw.flush()是把内容从缓冲区刷入到文件中去, 但是 fw.close()方法是先把内容从缓冲区刷入到文件中去即先调用 flush 方法, 所以 fw.flush()可以不用
FileWrite 在写时的换行与续写
- // 获取系统换行的符号
- private static final String LINE_SEPARATOR = System.getProperty("line.separator");
- public static void function_demo2() throws IOException {
- FileWriter writer = new FileWriter("demo.txt", true);// 创建写入流对象
- // 把内容写入到缓冲区
- writer.write("abcdef 绵" + LINE_SEPARATOR + "中国人啊吼叫职了");
- // 把缓冲区里的内容刷入到文件系统中
- // writer.flush();
- // 关闭流, 在关闭之前会先把缓冲区里的内容刷入到文件系统然后才关闭流; 若用此关闭流可不用手动调用 flush
- writer.close();
- }
注: FileWriter 在支持续写的时候提供了一个带两个参数的构造函数, 当传递为 true 时即可支持续写; 换行可调用系统提供的换行符号
四, 字符流 FileReader
- public static void function_demo3() throws IOException {
- // 创建读取流对象, 指定需要读取的文件地址
- FileReader reader = new FileReader("demo.txt");
- // 声明一个变量接收读取到的字符
- int ch;
- // 调用 read 方法读取文件中的字符, 当读取到文件的末尾的时候 read 方法返回 - 1
- while ((ch = reader.read()) != -1) {
- System.out.println((char) ch);
- }
- // 关闭流
- reader.close();
- }
注: 此读取方式为一个字符的读取, 每读取一个字符便写到控制台, 以下代码演示高效的读取, 即声明一个缓冲区的数组, 把每次所读到的内容先放入缓冲数组中去, 然后再一次性写到文件中
- public static void function_demo4() throws IOException {
- // 读取流对象
- FileReader reader = new FileReader("demo.txt");
- // 每次读取到的字符放入的缓冲数组区
- char[] buf = new char[1024];
- // 每次读取到的字符数
- int i;
- // 循环读取, 每次 read 一次把读取到的内容放入 buf 字符数组, 读到最后会返回 - 1
- while ((i = reader.read(buf)) != -1) {
- // 把读取到的字符转为字符串, 每次转换的数量为读取到的字符数
- System.out.println(new String(buf, 0, i));
- }
- reader.close();
- }
下面用两种方式实现文件的复制功能
- private static void function_demo5() throws IOException {
- FileReader fr = new FileReader("demo.txt");// 创建读取流对象
- FileWriter fw = new FileWriter("demo2.txt");// 创建写入流对象, 若文件不存在则创建; 若存在则覆盖
- int ch;// 存储读取到的字符
- // 循环读取文件中的数据
- while ((ch = fr.read()) != -1) {
- fw.write(ch);// 把每次读到的内容写入到新文件中
- }
- fw.close();// 关闭
- fr.close();// 关闭
- }
高效的复制方式
- private static void function_demo6() throws IOException {
- FileReader fr = new FileReader("demo.txt");// 创建读取流对象
- FileWriter fw = new FileWriter("demo3.txt");// 创建写入流对象, 若文件不存在则创建, 若存在则覆盖
- char[] buf = new char[4096];// 缓存数组
- int ch;// 存储读取到的字符
- // 循环读取文件中的数据
- while ((ch = fr.read(buf)) != -1) {// 把每次读取到的内容放入缓存数组中
- fw.write(buf, 0, ch);// 从缓存数组中把内容读出来
- }
- fw.close();// 关闭流
- fr.close();// 关闭流
- }
五, 高效的读取流 BufferedReader
从字符输入流中读取文本, 缓冲各个字符, 从而实现字符, 数组和行的高效读取. 注意, 此类可以直接读取行, 由此也说明此类是专门为高效的读取文件数据的方式
- private static void function_demo7() throws IOException {
- FileReader fr = new FileReader("demo.txt");// 读取流对象
- BufferedReader bReader = new BufferedReader(fr);// 缓冲读取流对象, 需要传入读取 Reader 的实现类
- int ch;
- while ((ch = bReader.read()) != -1) {// 此 read 为增强了的 read 方法, 用的装饰器模式
- System.out.println((char) ch);
- }
- bReader.close();// 关闭该流并释放与之关联的所有资源; 即也把读取流的对象 fr 给关闭了, 不需要再手动调用 fr.close()
- }
带缓冲数组的读取方式
- private static void function_demo7() throws IOException {
- FileReader fr = new FileReader("demo.txt");// 读取流对象
- BufferedReader bReader = new BufferedReader(fr);// 缓冲读取流对象, 需要传入读取 Reader 的实现类
- int ch = 0;
- char[] buff = new char[1024];
- while ((ch = bReader.read(buff)) != -1) {// 此 read 为增强了的 read 方法, 用的装饰器模式
- System.out.println(new String(buff, 0, ch));
- }
- bReader.close();// 关闭该流并释放与之关联的所有资源; 即也把读取流的对象 fr 给关闭了, 不需要再手动调用 fr.close()
- }
读取行
- private static void function_demo8() throws IOException {
- FileReader fr = new FileReader("demo.txt");
- BufferedReader bReader = new BufferedReader(fr);
- String line = null;// 获取每次读到的行内容
- while ((line = bReader.readLine()) != null) {// 如果读取到了最后, 则返回 null
- System.out.println(line);
- }
- bReader.close();
- }
六, 高效的写入流 BufferedWriter
将文本写入字符输出流, 缓冲各个字符, 从而提供单个字符, 数组和字符串的高效写入. 此流写入的时候提供了一个 newLine 方法, 可换行.
- private static void function_demo9() throws IOException {
- FileWriter fw = new FileWriter("demo4.txt");
- BufferedWriter bw = new BufferedWriter(fw);
- bw.write("LioneTree");
- bw.newLine();
- bw.write("go kb go kb nnw huo kb");
- bw.close();
- }
七, 使用 BufferedReader 与 BufferedWriter 实现文件复制的功能
- private static void function_demo10() throws IOException {
- FileReader fReader = new FileReader("demo.txt");// 读取流对象
- BufferedReader bReader = new BufferedReader(fReader);// 缓冲读取流对象, 传入 fReader 读取流对象
- FileWriter fWriter = new FileWriter("demo5.txt");// 写入流对象
- BufferedWriter bWriter = new BufferedWriter(fWriter);// 缓冲写入流对象, 传入 bWriter 写入流对象
- String line=null;// 存储每次读取到的行内容
- while((line=bReader.readLine())!=null) {// 如果文件内容读完了则返回 null
- bWriter.write(line);// 写入读取到的每行内容
- bWriter.newLine();// 每读完一行则换行
- }
- bReader.close();// 关闭读取流对象
- bWriter.close();// 关闭写入流对象
- }
八, 跟踪行号的缓冲字符输入流 LineNumberReader
此类定义了方法 setLineNumber(int) 和 getLineNumber(), 它们可分别用于设置和获取当前行号; 字继承自 BufferedReader 类
- private static void function_demo11() throws IOException {
- FileReader fr = new FileReader("demo.txt");// 读取流对象
- LineNumberReader lnr = new LineNumberReader(fr);// 行号读取流对象, 需要传入读取流 fr 对象
- String line = null;// 存储读取到的内容
- lnr.setLineNumber(100);// 设置起始行号, 若不设置默认从 0 开始, 在读取到的每一行的末尾处自增 1
- while ((line = lnr.readLine()) != null) {// 按行读取
- System.out.println(lnr.getLineNumber() + " " + line);
- }
- lnr.close();
- }
来源: https://www.cnblogs.com/zw971084570/p/9983054.html