文章目录
I/O流是指从计算机的外设和程序之间传送的数据序列;输入流代表从计算机外设流入程序的数据序列,如通过键盘输入的数据;输出流代表从程序流向计算机外设的数据序列,如向屏幕打印数据。根据I/O流数据格式分类可以将I/O流分为字节流和字符流,本篇主要介绍字符流。
字符I/O流简要体系
原始字符流
FileReader
1. 构造方法
构造方法 | 说明 |
---|---|
FileReader(String fileName) | 字符输入流关联文件,文件路径以字符串形式给出 |
FileReader(File file) | 字符输入流关联文件,文件路径以File对象形式给出 |
关联的文件如果不存在就会抛出FileNotFoundException异常,路径如果是一个文件夹会提示拒绝访问。
2. 常用成员方法
成员方法 | 说明 |
---|---|
int read() | 从数据中读入一个字符,返回值为0-65535之间的整数,表示该字符的unicode码,碰到输入流结尾时返回-1 |
int read(char[] cbuf) | 读入一个字符数组,返回实际读入的字符数,碰到输入流结尾时返回-1,最多读入b.length个字节 |
void close() | 关闭这个输入流 |
字符集和字符编码
- 字符集是指多个字符的集合,字符编码是把字符集中的字符编码为指定集合中某一对象以便文本在计算机中存储和通过通信网络的传递。
- 常见的字符编码方式有GBK和Unicode。GBK编码规则的英文字符占用1个字节,中文字符占用2个字节;Unicode中UTF-8编码规则的英文字符占用1个字节,中文字符占用3个字节。
- 对字符串进行编码可以使用getBytes()方法,解码可以使用String的构造方法。
当FileReader对象调用read方法读取时,会先读取8192个字节把内部数组装满,随后从数组取出字节进行返回。取字节的时候会进行判断,取出一个是正数则说明是英文,会直接转换读取;取出一个是负数则说明是中文,会根据编码规则决定多读几个,再进行转换读取。
FileWriter
1. 构造方法
构造方法 | 说明 |
---|---|
FileWriter(String fileName) | 字符输出流关联文件,文件路径以字符串形式给出 |
FileWriter(String fileName, boolean append) | append若为Ture表示允许追加 |
FileWriter(File file) | 字符输出流关联文件,文件路径以File对象形式给出 |
FileWriter(File file, boolean append) | append若为Ture表示允许追加 |
2. 常用成员方法
成员方法 | 说明 |
---|---|
void write(int c) | 写出单个字符 |
void write(char[] cbuf) | 写出一个字符数组 |
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 close() | 冲刷并关闭输出流 |
void flush() | 冲刷输出流将缓冲数据发送到目的地 |
字符输出流写出数据,需要调用flush或close方法,数据才会写出。在JDK7版本以后,可以使用将需要调用close方法的对象放到try()的括号里面,将在代码块结束后自动关流。
//读入和写出单个字符
try(FileReader fr1=new FileReader("E:\\A.txt");
FileWriter fw1=new FileWriter("E:\\AA.txt")){
int c;
while((c=fr1.read())!=-1){
fw1.write(c);
}
} catch (IOException e){
e.printStackTrace();
}
//读入和写出字符数组
try(FileReader fr2=new FileReader("E:\\B.txt");
FileWriter fw2=new FileWriter("E:\\BB.txt")){
char[] c=new char[1024*8];
int len;
while((len=fr2.read(c))!=-1){
fw2.write(c);
}
} catch (IOException e){
e.printStackTrace();
}
字符缓冲流
BufferedReader和BufferedWriter采用缓冲区来读写数据,以减少读写次数从而加快输入输出速度。输入时,数据成块地读入缓冲区,然后再从缓冲区读取单个字符;输出时与此相反。
BufferedReader
1. 构造方法
构造方法 | 说明 |
---|---|
BufferedReader(Reader r) | 把低级的字符输入流包装成字符缓冲流管道 |
2. 新增的成员方法
成员方法 | 说明 |
---|---|
String readLine() | 读取一行数据返回为字符串,如果没有数据可读则返回null |
BufferedWriter
1. 构造方法
构造方法 | 说明 |
---|---|
BufferedWriter(Reader r) | 把低级的字符输入流包装成字符缓冲流管道 |
2. 新增的成员方法
成员方法 | 说明 |
---|---|
void newLine() | 换行 |
//使用缓冲流进行读入和写出
try(BufferedReader br=new BufferedReader(new FileReader("E:\\C.txt"));
BufferedWriter bw=new BufferedWriter(new FileWriter("E:\\CC.txt"))){
int c;
while((c= br.read())!=-1){
bw.write(c);
}
} catch (IOException e){
e.printStackTrace();
}
//使用缓冲流按行读入和写出
try(BufferedReader br=new BufferedReader(new FileReader("E:\\C.txt"));
BufferedWriter bw=new BufferedWriter(new FileWriter("E:\\CC.txt"))){
String s;
while((s=br.readLine())!=null){
bw.write(s);
bw.newLine();
}
} catch (IOException e){
e.printStackTrace();
}
转换流
InputStreamReader和OutputStreamReader用于实现字符与字节之间的转化。所使用的编码和解码方案可在构造方法中指定,如果没有指定则使用系统默认的编码和解码方案。
InputStreamReader
解码:从文件读入的字节经InputStreamReader按指定的解码方案将字节转换为字符再输入。
作用:解决不同编码时,字符流读取文本内容乱码的问题。
思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流。
构造方法 | 说明 |
---|---|
InputStreamReader(InputStream is, String charset) | 把原始字节的输入流按照指定字符集编码转成字符输入流 |
OutputStreamWriter
编码:从程序读出的字符经OutputStreamWriter按指定的编码方案将字符转换为字节输出。
作用:控制写出去的字符是用什么字符集编码。
思路:获取字节输出流,按照指定的字符集编码将其转换成字符输出流。
构造方法 | 说明 |
---|---|
OutputStreamWriter(OutputStream os, String charset) | 把原始的字节输出流按照指定编码转换成字符输出流 |
//使用缓冲流对字符转换流进行换行读入和写出
try(BufferedReader br=new BufferedReader
(new InputStreamReader(new FileInputStream("E:\\D.txt"),"UTF-8"));
BufferedWriter bw=new BufferedWriter
(new OutputStreamWriter(new FileOutputStream("E:\\DD.txt"),"GBK"))){
String s;
while((s=br.readLine())!=null){
bw.write(s);
bw.newLine();
}
} catch (IOException e){
e.printStackTrace();
}
字符打印流
PrintWriter
PrintWriter是以文本打印的方式将对象、字符串、数值向文件输出。与前面的I/O类不同的是,PrintWriter的构造方法和成员方法不会抛出IOException,所以不需要在try-catch块中调用它们。
1. 构造方法
构造方法 | 说明 |
---|---|
PrintWriter(File file) | 打印流通向文件 |
PrintWriter(File file, String csn) | 打印流通向文件,可以指定写出的字符编码 |
PrintWriter(OutputStream out) | 打印流通向字节输出流 |
PrintWriter(Writer out) | 打印流通向字符输出流 |
PrintWriter(String fileName) | 打印流通向文件路径 |
PrintWriter(String fileName, Charset charset) | 打印流通向文件路径,可以指定写出的字符编码 |
2. 常用成员方法
成员方法 | 说明 |
---|---|
void println(XXX xxx) | 打印任意类型的数据出去 |
PrintStream和PrintWriter的比较
两者功能基本相同,PrintStream能做的PrintWriter也都能实现,并且PrintWriter的功能更为强大。但是由于PrintWriter出现的比较晚,较早的System.out使用的是PrintStream来实现的,所以为了兼容就没有废弃PrintStream。
两者最大的差别是,PrintStream在输出字符,将字符转换为字节时采用的是系统默认的编码格式,这样当数据传输另一个平台,而另一个平台使用另外一个编码格式解码时就会出现问题,存在不可控因素。而PrintWriter可以在传入Writer时可由程序员指定字符转换为字节时的编码格式,这样兼容性和可控性会更好。