字符流
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的方法。
使用
使用步骤与文件字节输入流几乎一致!也是三种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对象。 |
使用步骤
- 创建FileWriter对象,构造方法中绑定要写入的目的地
- 使用FileWriter中的方法write,把数据写入到内存缓冲区中(有一个字符转成字节的过程)
- 使用FileWriter对象的flush方法,把内存缓冲区中的数据,刷新到文件中。!与字节输出流的区别在此!
- 释放资源(会先把内存缓冲区的数据刷新到文件再关闭资源)
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("
");
char[] buf = {'a', 'b', 'c', 'd', 'e'};
fw.write(buf);
fw.write("
");
fw.write(buf,0,3);
fw.write("
");
fw.write("233");
fw.write("
");
fw.write("123456",3,3);
fw.write("
");
// 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的也做了些改进,但不好用就不写了