本文目录导读:

我来介绍几个实用的Java文件读写提速案例和具体操作步骤:
使用缓冲流(最基础实用的提速方法)
案例:大文件复制(100MB+)
// ❌ 慢速方式 - 不使用缓冲
try (FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt")) {
int data;
while ((data = fis.read()) != -1) {
fos.write(data);
}
}
// ✅ 快速方式 - 使用缓冲流
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("input.txt"), 8192); // 8KB缓冲区
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("output.txt"), 8192)) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
}
// 性能提升:10-100倍
内存映射文件(超大文件最佳方案)
案例:处理GB级日志文件
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class MappedFileDemo {
public static void main(String[] args) throws Exception {
// 读取2GB的日志文件
try (FileChannel channel = FileChannel.open(
Paths.get("huge-log.txt"),
StandardOpenOption.READ)) {
long fileSize = channel.size();
// 分块映射,避免内存溢出
long chunkSize = 100 * 1024 * 1024; // 100MB每块
for (long position = 0; position < fileSize; position += chunkSize) {
long size = Math.min(chunkSize, fileSize - position);
MappedByteBuffer buffer = channel.map(
FileChannel.MapMode.READ_ONLY, position, size);
// 直接操作内存中的数据,无需复制
processData(buffer);
}
}
}
private static void processData(MappedByteBuffer buffer) {
// 直接在内存中处理数据
while (buffer.hasRemaining()) {
byte b = buffer.get();
// 处理每个字节...
}
}
}
// 性能提升:比传统IO快5-10倍
使用NIO批量读取
案例:CSV文件快速处理
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class NIOBatchReadDemo {
public static List<String> fastReadLines(String filename) throws Exception {
List<String> lines = new ArrayList<>();
try (FileChannel channel = FileChannel.open(
Path.of(filename), StandardOpenOption.READ)) {
// 分配大缓冲区
ByteBuffer buffer = ByteBuffer.allocateDirect(64 * 1024); // 64KB
StringBuilder lineBuilder = new StringBuilder();
while (channel.read(buffer) != -1) {
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
// 处理当前批次的数据
String chunk = new String(bytes, StandardCharsets.UTF_8);
String[] chunkLines = chunk.split("\n", -1);
for (int i = 0; i < chunkLines.length; i++) {
if (i == 0) {
// 拼接上一批次未完成的行
chunkLines[i] = lineBuilder + chunkLines[i];
}
if (i < chunkLines.length - 1) {
lines.add(chunkLines[i]);
} else {
// 最后一行可能不完整,保存到builder
lineBuilder = new StringBuilder(chunkLines[i]);
}
}
buffer.clear();
}
// 处理最后一行
if (lineBuilder.length() > 0) {
lines.add(lineBuilder.toString());
}
}
return lines;
}
}
// 性能提升:比BufferedReader快30-50%
并行处理(多核CPU最佳实践)
案例:快速统计JSON文件中的特定数据
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.atomic.LongAdder;
import java.util.stream.Stream;
public class ParallelFileProcessing {
public static long countLines(String filename) throws Exception {
LongAdder counter = new LongAdder();
// 使用并行流处理
try (Stream<String> lines = Files.lines(Path.of(filename))) {
lines.parallel()
.filter(line -> line.contains("ERROR"))
.forEach(line -> {
// 处理匹配的行
counter.increment();
// 可以在这里添加更多的处理逻辑
// 注意线程安全
});
}
return counter.sum();
}
// 更复杂的分块并行处理
public static void parallelChunkProcessing(String filename) throws Exception {
long fileSize = Files.size(Path.of(filename));
int chunkCount = Runtime.getRuntime().availableProcessors(); // CPU核心数
long chunkSize = fileSize / chunkCount;
Thread[] threads = new Thread[chunkCount];
for (int i = 0; i < chunkCount; i++) {
final int chunkIndex = i;
long start = chunkIndex * chunkSize;
long end = (chunkIndex == chunkCount - 1) ?
fileSize : (chunkIndex + 1) * chunkSize;
threads[i] = new Thread(() -> {
processFileChunk(filename, start, end);
});
threads[i].start();
}
// 等待所有线程完成
for (Thread thread : threads) {
thread.join();
}
}
private static void processFileChunk(String filename, long start, long end) {
// 实现块处理逻辑
System.out.printf("Processing chunk: %d - %d%n", start, end);
}
}
// 性能提升:根据CPU核心数,可提升2-8倍
最佳实践组合方案
完整案例:高性能文件读取器
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
public class HighPerformanceFileReader {
private static final int BUFFER_SIZE = 64 * 1024; // 64KB
private static final int DIRECT_BUFFER = true;
/**
* 高性能文件读取器
* @param filename 文件名
* @param consumer 数据处理回调
*/
public static void fastRead(String filename, Consumer<String> consumer)
throws Exception {
try (FileChannel channel = FileChannel.open(
Path.of(filename), StandardOpenOption.READ)) {
ByteBuffer buffer;
if (DIRECT_BUFFER) {
buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
} else {
buffer = ByteBuffer.allocate(BUFFER_SIZE);
}
StringBuilder leftover = new StringBuilder();
while (channel.read(buffer) != -1) {
buffer.flip();
// 转换为字符串
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
String data = leftover + new String(bytes, StandardCharsets.UTF_8);
// 按行处理
int lastNewLine = data.lastIndexOf('\n');
if (lastNewLine >= 0) {
String completeData = data.substring(0, lastNewLine);
String[] lines = completeData.split("\n");
for (String line : lines) {
consumer.accept(line.trim());
}
leftover = new StringBuilder(data.substring(lastNewLine + 1));
} else {
leftover.append(data);
}
buffer.clear();
}
// 处理最后剩余数据
if (leftover.length() > 0) {
consumer.accept(leftover.toString().trim());
}
}
}
// 使用示例
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
fastRead("large-file.txt", line -> {
// 处理每一行
if (line.startsWith("ERROR")) {
System.out.println("Found error: " + line);
}
});
long end = System.currentTimeMillis();
System.out.println("Processing time: " + (end - start) + "ms");
}
}
性能对比测试代码
public class PerformanceTest {
public static void main(String[] args) throws Exception {
String testFile = "test-100mb.txt";
int iterations = 5;
// 测试不同方式
for (int i = 0; i < iterations; i++) {
System.out.println("=== Iteration " + (i + 1) + " ===");
// 1. 传统FileReader
long time1 = testMethod(
() -> readWithFileReader(testFile));
System.out.println("FileReader: " + time1 + "ms");
// 2. BufferedReader
long time2 = testMethod(
() -> readWithBufferedReader(testFile));
System.out.println("BufferedReader: " + time2 + "ms");
// 3. NIO with buffer
long time3 = testMethod(
() -> readWithNIO(testFile));
System.out.println("NIO Buffer: " + time3 + "ms");
// 4. MappedByteBuffer
long time4 = testMethod(
() -> readWithMappedFile(testFile));
System.out.println("MappedByteBuffer: " + time4 + "ms");
System.out.println();
}
}
private static long testMethod(Runnable method) throws Exception {
long start = System.nanoTime();
method.run();
return (System.nanoTime() - start) / 1_000_000;
}
// 各方法的实现...
}
- 首选方案:BufferedReader + BufferedWriter,简单有效
- 大文件(>100MB):使用MappedByteBuffer
- 追求极致性能:NIO + 直接缓冲区(allocateDirect)
- 多核CPU:并行处理(注意线程安全)
- 关键优化点:
- 缓冲区大小:通常8-64KB
- 使用直接缓冲区(Direct Buffer)避免数据拷贝
- 批量处理代替逐字节处理
选择合适的方案可以轻松获得10-100倍的性能提升。