Java - IO - 字符流

字符流

Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。

字符输入流(Reader)

java.io.Reader抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。

  • public int read(): 从输入流读取一个字符。
  • public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。
  • public void close() :关闭此流并释放与此流相关联的任何系统资源。

FileReader类

java.io.FileReader 类是用于读取字符文件的类。构造时使用系统默认的字符编码和默认字节缓冲区。

构造方法
Constructor Description
FileReader(File file) 创建一个新的 FileReader ,给定要读取的File对象。
FileReader(String fileName) 创建一个新的 FileReader ,给定要读取的文件的名称。

FileReader类中没有自己写方法,都是继承了父类InputStreamReader的方法。

image-20200519150222900

使用

使用步骤与文件字节输入流几乎一致!也是三种read方法

方法 描述
int read() 从此输入流中读取一个数据字节。
int read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
int read(byte[] b, int off, int len) 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
void close() 关闭此文件输入流并释放与此流有关的所有系统资源。

例子

package characterstream;

import java.io.FileReader;
import java.io.IOException;

public class TestReader {
    public static void main(String[] args) throws IOException {
        // 1.创建FileReader对象
        FileReader fr = new FileReader("test.txt");
        // 2.使用read()方法逐个读取字符
        int len = 0;
        while ((len = fr.read()) != -1) {
            System.out.println((char)len);
        }
        // 3.释放资源
        fr.close();
    }
}

字符输出流(Writer)

java.io.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 类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

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

构造方法
Constructor Description
FileWriter(File file) 创建一个新的 FileWriter,给定要读取的File对象。
FileWriter(File file, boolean append) 给一个File对象构造一个FileWriter对象。append为true追加内容。
FileWriter(String fileName) 创建一个新的 FileWriter,给定要读取的文件的名称。
FileWriter(String fileName, boolean append) 构造一个给定文件名的FileWriter对象。append为true追加内容。
FileWriter(FileDescriptor fd) 构造与文件描述符关联的FileWriter对象。
使用步骤
  1. 创建FileWriter对象,构造方法中绑定要写入的目的地
  2. 使用FileWriter中的方法write,把数据写入到内存缓冲区中(有一个字符转成字节的过程)
  3. 使用FileWriter对象的flush方法,把内存缓冲区中的数据,刷新到文件中。!与字节输出流的区别在此!
  4. 释放资源(会先把内存缓冲区的数据刷新到文件再关闭资源)
package characterstream;

        import java.io.FileWriter;
        import java.io.IOException;

public class TestWriter {
    public static void main(String[] args) throws IOException {
        // 1. 创建FileWriter对象,构造方法中绑定要写入的目的地
        FileWriter fw = new FileWriter("test.txt");
        // 2. 使用FileWriter中的方法write,把数据写入到内存缓冲区中(有一个字符转成字节的过程)
        fw.write('0');
        fw.write("\r\n");

        char[] buf = {'a', 'b', 'c', 'd', 'e'};
        fw.write(buf);
        fw.write("\r\n");

        fw.write(buf,0,3);
        fw.write("\r\n");

        fw.write("233");
        fw.write("\r\n");

        fw.write("123456",3,3);
        fw.write("\r\n");
        // 3. 使用FileWriter对象的flush方法,把内存缓冲区中的数据,刷新到文件中。!与字节输出流的区别在此!
        fw.flush();
        // 4. 释放资源(会先把内存缓冲区的数据刷新到文件再关闭资源)
        fw.close();
    }
}

注意文件字符输出类可以直接写字符串,而文件字节输出流需要将字符串转成字节数组。

test.txt内容

0
abcde
abc
233
456

IO异常的处理

JDK7之前处理

之前的入门练习,我们一直把异常抛出,而实际开发中并不能这样处理,建议使用try...catch...finally 代码块,

处理异常部分,代码使用演示:

package characterstream;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * jdk7之前的IO异常处理方式
 */
public class CopyJDK7 {
    public static void main(String[] args) {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader("data1.txt");
            fw = new FileWriter("data2.txt");

            // 注意这里已经不是字节流,不是byte[]
            char[] bytes = new char[1024];
            int len = 0;
            while ((len = fr.read(bytes)) != -1) {
                fw.write(bytes, 0, len);
                fw.flush();
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {

            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            }

            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            }
        }

    }
}

看着这么多大括号,太影响代码的可读性了!

JDK7的处理(扩展知识)

JDK7优化后的try-with-resource 语句,该语句确保了每个资源在语句结束时关闭。

所谓的资源(resource)是指在程序完成后,必须关闭的对象。

package characterstream;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * jdk7的新特性:
 * try (创建流对象语句,如果创建多个流使用';'隔开) {
 * // 读写数据
 * } catch (IOException e) {
 * // 异常处理
 * }
 */
public class CopyJDK7 {
    public static void main(String[] args) {
        // JDK7新特性,在try后面加个括号并在里面定义流对象,会自动释放资源
        try (FileReader fr = new FileReader("data1.txt");
             FileWriter fw = new FileWriter("data2.txt")) {
            // 逻辑代码不变,定义提前
            char[] bytes = new char[1024];
            int len = 0;
            while ((len = fr.read(bytes)) != -1) {
                fw.write(bytes, 0, len);
                fw.flush();
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
        
        System.out.println("复制完成");
    }
}

JDK9的也做了些改进,但不好用就不写了

posted @ 2020-05-31 16:15  小橘子ღ  阅读(239)  评论(0编辑  收藏  举报