Java文件写入和写出
Java读取和写入
纯文本内容
try-with-resources
语句确保了在操作完成后,BufferedReader
和BufferedWriter
会被自动关闭。
// 源文件路径
String source = "D:\\dir\\source\\plain text.md";
// 目标文件路径
String target = "D:\\dir\\target\\plain text.md";
try (
// 创建读取和写入流
BufferedReader reader = new BufferedReader(new FileReader(source));
BufferedWriter writer = new BufferedWriter(new FileWriter(target))
) {
// 读取源文件并写入目标文件
String line = reader.readLine();
while (line != null) {
writer.write(line);
writer.newLine();
line = reader.readLine();
}
} catch (IOException exception) {
System.out.println(exception.getMessage());
}
读取和写入流媒体内容
如果流媒体内容很大,建议缓存区也设置大点,这样可以减少读写操作的次数,因为每次读写操作可以处理更多的数据。这可以显著提高大文件的复制速度。
如果想要更好的性能可以看下面的Java的NIO
// 源文件路径
String sourcePath = "D:\\dir\\source\\video.ts";
// 目标文件路径
String targetPath = "D:\\dir\\target\\video.ts";
try (
// 创建FileInputStream来读取源文件
FileInputStream reader = new FileInputStream(sourcePath);
// 创建BufferedWriter来写入目标文件
FileOutputStream writer = new FileOutputStream(targetPath)
) {
// 创建缓冲区
byte[] buffer = new byte[1024 * 6];
int length;
// 读取源文件并写入目标文件
while ((length = reader.read(buffer)) > 0) writer.write(buffer, 0, length);
} catch (IOException exception) {
System.out.println(exception.getMessage());
}
读取和写入流媒体内容-NIO的FileChannel
系统调用(如read
和write
)通常比用户空间的函数调用要慢。通过减少这些调用的次数,可以提高性能。例如,使用transferTo
或transferFrom
方法可以直接在文件通道之间传输数据,而不需要通过用户空间。
// 源文件路径
String sourcePath = "D:\\dir\\source\\video.ts";
// 目标文件路径
String targetPath = "D:\\dir\\target\\video.ts";
try (
FileInputStream inputStream = new FileInputStream(sourcePath);
FileOutputStream outputStream = new FileOutputStream(targetPath);
FileChannel sourceChannel = inputStream.getChannel();
FileChannel targetChannel = outputStream.getChannel()
) {
long position = 0;
long count = sourceChannel.size();
while (position < count) {
position += sourceChannel.transferTo(position, count - position, targetChannel);
}
} catch (IOException exception) {
System.out.println(exception.getMessage());
}
多线程或异步I/O
对于非常大的文件,可以使用多线程来同时读取和写入数据。Java的
NIO
包提供了非阻塞I/O和选择器,可以用来实现高效的多线程文件复制。使用NIO的
FileChannel
FileChannel
提供了更高效的文件I/O操作,特别是对于大文件。它支持直接内存访问,可以减少数据在用户空间和内核空间之间的复制。
比较流媒体读写性能
未使用NIO
复制耗时: 614 毫秒
// 开始复制时间
LocalDateTime start = LocalDateTime.now();
// 源文件路径
String sourcePath = "D:\\dir\\source\\video.ts";
// 目标文件路径
String targetPath = "D:\\dir\\target\\video.ts";
try (
// 创建FileInputStream来读取源文件
FileInputStream reader = new FileInputStream(sourcePath);
// 创建BufferedWriter来写入目标文件
FileOutputStream writer = new FileOutputStream(targetPath)
) {
// 创建缓冲区
byte[] buffer = new byte[1024 * 7];
int length;
// 读取源文件并写入目标文件
while ((length = reader.read(buffer)) > 0) writer.write(buffer, 0, length);
} catch (IOException exception) {
System.out.println(exception.getMessage());
}
// 计算时间差
LocalDateTime end = LocalDateTime.now();
Duration duration = Duration.between(start, end);
System.out.println("复制耗时: " + duration.toMillis() + " 毫秒");// 复制耗时: 614 毫秒
使用NIO
复制耗时: 325 毫秒
// 开始复制时间
LocalDateTime start = LocalDateTime.now();
// 源文件路径
String sourcePath = "D:\\dir\\source\\video.ts";
// 目标文件路径
String targetPath = "D:\\dir\\target\\video.ts";
try (
FileInputStream inputStream = new FileInputStream(sourcePath);
FileOutputStream outputStream = new FileOutputStream(targetPath);
FileChannel sourceChannel = inputStream.getChannel();
FileChannel targetChannel = outputStream.getChannel()
) {
long position = 0;
long count = sourceChannel.size();
while (position < count) {
position += sourceChannel.transferTo(position, count - position, targetChannel);
}
} catch (IOException exception) {
System.out.println(exception.getMessage());
}
// 计算时间差
LocalDateTime end = LocalDateTime.now();
Duration duration = Duration.between(start, end);
System.out.println("复制耗时: " + duration.toMillis() + " 毫秒");// 复制耗时: 325 毫秒
对比发现几乎快了一倍