Java字符流(字符输入流+字符输出流)

字符流是针对字符数据的特点进行过优化的,因而提供一些面向字符的有用特性,字符流的源或目标通常是文本文件。

Reader 和 Writer 是 java.io 包中所有字符流的父类。由于它们都是抽象类,所以应使用它们的子类来创建实体对象,利用对象来处理相关的读写操作。Reader 和 Writer 的子类又可以分为两大类:
  • 一类用来从数据源读入数据或往目的地写出数据(称为节点流);
  • 另一类对数据执行某种处理(称为处理流)。

Java 字符输入流

面向字符的输入流类都是 Reader 的子类,其类层次结构如图 1 所示。
Reader的类层次结构图
图1:Reader 类层次结构图

表1列出了 Reader 的主要子类及说明。
表1:Reader 的主要子类
类名 功能描述
CharArrayReader 从字符数组读取的输入流
BufferedReader 缓冲输入字符流
PipedReader 输入管道
InputStreamReader 将字节转换到字符的输入流
FilterReader 过滤输入流
StringReader 从字符串读取的输入流
LineNumberReader 为输入数据附加行号
PushbackReader 返回一个字符并把此字节放回输入流
FileReader 从文件读取的输入流

Reader 所提供的方法如表2所示,可以利用这些方法来获得流内的位数据。
表2:Reader 的常用方法
方法 功能描述
void close() 关闭输入流
void mark() 标记输入流的当前位置
boolean markSupported() 测试输入流是否支持 mark
int read() 从输入流中读取一个字符
int read(char[] ch) 从输入流中读取字符数组
int read(char[] ch, int off, int len) 从输入流中读 len 长的字符到 ch 内
boolean ready() 测试流是否可以读取
void reset() 重定位输入流
long skip(long n) 跳过流内的 n 个字符

使用 FileReader 类读取文件

FileReader 类是 Reader 子类 InputStreamReader 类的子类,因此 FileReader 类既可以使用 Reader 类的方法也可以使用 InputStreamReader 类的方法来创建对象。

在使用 FileReader 类读取文件时,必须先调用 FileReader() 构造方法创建 FileReader 类的对象,再调用 read() 方法。FileReader 构造方法的格式为:

public FileReader(String name);  //根据文件名创建一个可读取的输入流对象

name 为文件名,包含文件路径。

【示例1】利用 FileReader 类读取纯文本文件的内容。
import java.io.*;
class Demo{
    public static void main(String args[]) throws IOException{
        char a[]=new char[1000]; //创建可容纳 1000 个字符的数组
        FileReader b=new FileReader("www.weixueyuan.net.txt");
        int num=b.read(a); //将数据读入到数组 a 中,并返回字符数
        String str=new String(a, 0, num); //将字符串数组转换成字符串
        System.out.println("读取的字符个数为:" + num + ",内容为:");
        System.out.println(str);
    }
}
运行结果:

读取的字符个数为:87,内容为:
欢迎来到 www.weixueyuan.net 学习 Java 编程,它已经7岁了。

www.weixueyuan.net 专注于分享优质编程教程,帮助对编程感兴趣的读者。


需要注意的是,Java 把一个汉字或英文字母作为一个字符对待,回车或换行作为两个字符对待。

使用 BufferedReader 类读取文件

BufferedReader 类是用来读取缓冲区中的数据。使用时必须创建 FileReader 类对象,再以该对象为参数创建 BufferedReader 类的对象。BufferedReader 类有两个构造方法,其格式为:

public BufferedReader(Reader in);  //创建缓冲区字符输入流
public BufferedReader(Reader in,int size);  //创建输入流并设置缓冲区大小


【示例2】利用 BufferedReader 类读取纯文本文件的内容。
import java.io.*;
class Demo{
    public static void main(String args[]) throws IOException{
        String OneLine;
        int count=0;
        try{
                FileReader a=new FileReader("www.weixueyuan.net.txt");
                BufferedReader b=new BufferedReader(a);
                while((OneLine=b.readLine())!=null){  //每次读取 1 行
                     count++;  //计算读取的行数
                     System.out.println(OneLine);
                }
                System.out.println("\n共读取了"+count+"行");
                b.close();
           }
           catch(IOException io){
                System.out.println("出错了!"+io);
           }
      }
}
运行结果:

欢迎来到 www.weixueyuan.net 学习 Java 编程,它已经7岁了。

www.weixueyuan.net 专注于分享优质编程教程,帮助对编程感兴趣的读者。

共读取了3行


需要注意的是,执行 read() 或 write() 方法时,可能由于 IO 错误,系统抛出 IOException 异常,需要将执行读写操作的语句包括在 try 块中,并通过相应的 catch 块来处理可能产生的异常。

Java 字符输出流

面向字符的输出流都是类 Writer 的子类,其类层次结构如图2所示。
Writer的类层次结构图
图2:Writer 类层次结构图

表3列出了 Writer 的主要子类及说明。
表3:Writer 的主要子类
类名 功能说明
CharArrayWriter 写到字符数组的输出流
BufferedWriter 缓冲输出字符流
PipedWriter 输出管道
OutputStreamWriter 转换字符到字节的输出流
FilterWriter 过滤输出流
StringWriter 输出到字符串的输出流
PrintWriter 包含 print()和 println()的输出流
FileWriter 输出到文件的输出流

Writer 所提供的方法如表4所示。
表4:Writer 的常用方法
方法 功能描述
void close() 关闭输出流
void flush() 将缓冲区中的数据写到文件中
void writer(int c) 将单一字符 c 输出到流中
void writer(String str) 将字符串 str 输出到流中
void writer(char[] ch) 将字符数组 ch 输出到流
void writer(char[] ch, int offset, int length) 将一个数组内自 offset 起到 length 长的字符输出到流

使用 FileWriter 类写入文件

FileWriter 类是 Writer 子类 OutputStreamWriter 类的子类,因此 FileWriter 类既可以使用 Writer 类的方法也可以使用 OutputStreamWriter 类的方法来创建对象。

在使用 FileWriter 类写入文件时,必须先调用 FileWriter() 构造方法创建 FileWriter 类的对象,再调用 writer()方法。FileWriter 构造方法的格式为:

public FileWriter(String name);  //根据文件名创建一个可写入的输出流对象
public FileWriter(String name,Boolean a);  //a 为真,数据将追加在文件后面


【示例3】利用 FileWriter 类将 ASCII 字符写入到文件中。
import java.io.*;
class Demo{
    public static void main(String args[]){
        try{
            FileWriter a=new FileWriter("www.weixueyuan.net.txt");
            for(int i=32;i<126;i++){
                a.write(i);
            }
            a.close();
        }
        catch(IOException e){}
    }
}
运行后程序后,打开 www_weixueyuan_net.txt 文件,显示内容为:

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}

使用 BufferedWriter 类写入文件

BufferedWriter 类是用来将数据写入到缓冲区。使用时必须创建 FileWriter 类对象,再以该对象为参数创建 BufferedWriter 类的对象,最后需要用 flush() 方法将缓冲区清空。BufferedWriter 类有两个构造方法,其格式为:

public BufferedWriter(Writer out);  //创建缓冲区字符输出流
public BufferedWriter(Writer out,int size);  //创建输出流并设置缓冲区大小


【示例4】利用 BufferedWriter 类进行文件复制。
import java.io.*;
class Demo{
    public static void main(String args[]){
        String str=new String();
        try{
            BufferedReader in=new BufferedReader(new FileReader("www.weixueyuan.net.txt"));
            BufferedWriter out=new BufferedWriter(new FileWriter("www.weixueyuan.net_2.txt"));
            while((str=in.readLine())!=null){
                System.out.println(str);
                out.write(str);  //将读取到的 1 行数据写入输出流
                out.newLine();  //写入换行符
            }
            out.flush();
            in.close();
            out.close();
        }
        catch(IOException e){
            System.out.println("出现错误"+e);
        }
    }
}
需要注意的是,调用 out 对象的 write() 方法写入数据时,不会写入回车,因此需要使用 newLine() 方法在每行数据后加入回车,以保证目标文件与源文件相一致。