当谈到字符流Reader
和Writer
时,我们通常指的是字符输入流和字符输出流,它们是用于读取和写入字符数据的Java I/O类。
Reader
类是用于从字符流中读取字符数据的抽象类。它提供了许多方法来读取字符,包括单个字符、字符数组和字符缓冲区。一些常用的Reader
的子类包括FileReader
、InputStreamReader
和StringReader
。
Writer
类是用于将字符数据写入字符流的抽象类。它提供了许多方法来写入字符,包括单个字符、字符数组和字符串。一些常用的Writer
的子类包括FileWriter
、OutputStreamWriter
和StringWriter
。
这些字符流类在处理字符数据时有几个重要的特点:
-
缓冲区:字符流一般都提供了内部缓冲区,以提高读写效率。缓冲区会在一定条件下自动刷新,将数据从缓冲区写入到底层数据源(如文件)或从底层数据源读取到缓冲区。
-
字符编码:字符流在读取和写入字符时,需要使用字符编码来将字符转换为字节或将字节转换为字符。常用的字符编码包括ASCII、UTF-8和UTF-16等。在创建字符流对象时,可以指定字符编码或使用系统默认编码。
-
异常处理:字符流在读取和写入过程中可能会抛出异常,如文件不存在、读取错误等。因此,在使用字符流时,需要适当处理这些异常,以确保程序的健壮性。
下面是一个简单的示例,演示如何使用Reader
和Writer
读取和写入文件:
import java.io.*;
public class CharacterStreamsExample {
public static void main(String[] args) {
try {
// 创建一个Reader读取文件
Reader reader = new FileReader("input.txt");
// 创建一个Writer写入文件
Writer writer = new FileWriter("output.txt");
// 读取字符并写入到输出文件中
int data;
while ((data = reader.read()) != -1) {
writer.write(data);
}
// 关闭输入输出流
reader.close();
writer.close();
System.out.println("文件已成功读取和写入。");
} catch (IOException e) {
e.printStackTrace();
}
}
}
上述示例中,Reader
使用FileReader
创建一个读取文件的字符流,Writer
使用FileWriter
创建一个写入文件的字符流。然后,通过循环读取Reader
中的字符,并使用Writer
将字符写入到另一个文件中。最后,关闭输入输出流来释放系统资源。
这只是一个简单的示例,Reader
和Writer
提供了更多的方法和选项,以满足不同的读写需求。在实际应用中,我们可以根据具体情况选择适合的字符流类来读取和写入字符数据。
flush()
和close()
是Java的I/O类中常见的方法,用于刷新缓冲区和关闭流。虽然它们有一些相似之处,但它们的具体功能和用途是不同的。
-
flush()
方法:flush()
方法用于刷新输出流的缓冲区,将缓冲区中的数据立即写入到底层设备(如文件、网络等)中。它的主要作用是确保数据及时送达目标设备,而不是暂存在内存中等待进一步的写入操作。- 在调用
flush()
方法后,输出流可以继续写入数据,同时将已有的数据写入底层设备。这在一些需要实时发出数据的场景中非常有用,例如网络通信或日志记录。 flush()
方法并不关闭流,它只是清空输出缓冲区,使其中的数据立即写入目标设备。所以,在继续使用输出流之前,可能需要多次调用flush()
来确保所有数据都被写入。
-
close()
方法:close()
方法用于关闭流,释放与流相关的系统资源。它不仅会刷新缓冲区,还会关闭底层的输入/输出源,如文件、网络连接等。因此,在调用close()
方法后,流无法再被使用。close()
方法会自动调用flush()
方法,以确保缓冲区中的数据被完全写入底层设备。close()
方法是一种良好的编程习惯,它可以保证程序的正确运行和资源的释放,尤其是在涉及到系统资源(如文件、网络)的情况下。
在使用流时,通常建议在不再需要使用流时调用close()
方法,以确保资源被正确释放。但是,在某些情况下,可能需要显式调用flush()
方法来确保数据的即时性,而不等到流关闭时才刷新缓冲区。
总结:
flush()
方法用于刷新缓冲区,将数据写入到底层设备,但并不关闭流。close()
方法用于关闭流,并在关闭前调用flush()
方法确保数据写入底层设备。它释放与流相关的系统资源,因此流在关闭后无法再被使用。
字符复制功能的实现:
使用Reader
和Writer
实现文件复制功能可以通过一次读取一部分字符并一次写入一部分字符的方式来完成。下面是一个示例代码:
import java.io.*;
public class FileCopyExample {
public static void main(String[] args) {
String sourceFilePath = "source.txt";
String destinationFilePath = "destination.txt";
try (
Reader reader = new FileReader(sourceFilePath);
Writer writer = new FileWriter(destinationFilePath)
) {
char[] buffer = new char[1024];
int charactersRead;
while ((charactersRead = reader.read(buffer)) != -1) {
writer.write(buffer, 0, charactersRead);
}
System.out.println("文件复制成功。");
} catch (IOException e) {
e.printStackTrace();
}
}
}
上述代码首先打开源文件和目标文件的输入和输出字符流,使用FileReader
和FileWriter
来读取和写入文件。
然后,创建一个大小为1024的字符缓冲区。在循环中,通过read()
方法从源文件中读取字符数据到缓冲区,读取的字符数保存在charactersRead
变量中。
如果charactersRead
的值不等于-1,表示还有字符被读取。将缓冲区中的字符数据写入目标文件中,使用write()
方法指定写入的字符数。
循环继续,直到所有字符都被读取和写入。最后,关闭输入和输出流,并输出提示信息。
这样,我们就可以使用Reader
和Writer
来复制文件。请注意,在实际应用中,我们应该考虑异常处理和错误处理,以确保程序的健壮性和可靠性。