Java文件读取时间比较

在Java核心技术卷Ⅱ(原书第九版) 1.7节比较了几种文件操作时间,结论是内存映射文件速度明显快于随机访问文件速度。为何随机访问会慢20倍左右?写个程序验证一下。

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Test {
	// InputStream 和 RandomAccessFile 方法速度太慢, 只读取部分数据
	static int MAX_COUNT = 1024 * 1024;

	static void checkInputStream(Path fileName) throws IOException {
		long start = System.currentTimeMillis();
		long sum = 0L;
		try (InputStream in = Files.newInputStream(fileName)) {
			int c, cnt = 0;
			while ((c = in.read()) != -1) {
				sum += c;
				if (++cnt == MAX_COUNT)
					break;
			}
		}
		long end = System.currentTimeMillis();
		print(String.format("InputStream(%dKb)", MAX_COUNT / 1024), sum, end - start);
	}

	static void checkBufferedInputStream(Path fileName) throws IOException {
		long start = System.currentTimeMillis();
		long sum = 0L;
		try (InputStream in = new BufferedInputStream(Files.newInputStream(fileName))) {
			int c;
			while ((c = in.read()) != -1)
				sum += c;
		}
		long end = System.currentTimeMillis();
		print("BufferedInputStream", sum, end - start);
	}

	static void checkRandomAccessFile(Path fileName) throws IOException {
		long start = System.currentTimeMillis();
		long sum = 0L;
		try (RandomAccessFile in = new RandomAccessFile(fileName.toFile(), "r")) {
			int c, cnt = 0;
			while ((c = in.read()) != -1) {
				sum += c;
				if (++cnt == MAX_COUNT)
					break;
			}
		}
		long end = System.currentTimeMillis();
		print(String.format("RandomAccessFile(%dKb)", MAX_COUNT / 1024), sum, end - start);
	}

	static void checkBufferedRandomAccessFile(Path fileName, int bufSize) throws IOException {
		long start = System.currentTimeMillis();
		long sum = 0L;
		try (RandomAccessFile in = new RandomAccessFile(fileName.toFile(), "r")) {
			byte[] buf = new byte[bufSize];
			int count;
			while ((count = in.read(buf)) > 0) {
				for (int i = 0; i < count; i++) {
					sum += buf[i] & 0xFF;
				}
				if (count != bufSize) {
					break;
				}
			}
		}
		long end = System.currentTimeMillis();
		print(String.format("Buffered(%d) RandomAccessFile", bufSize), sum, end - start);
	}

	static void checkMappedFile(Path fileName) throws IOException {
		long start = System.currentTimeMillis();
		long sum = 0L;
		try (FileChannel channel = FileChannel.open(fileName)) {
			int length = (int) channel.size();
			MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, length);
			for (int i = 0; i < length; i++) {
				int c = buffer.get(i) & 0xFF;
				sum += c;
			}
		}
		long end = System.currentTimeMillis();
		print("MappedFile", sum, end - start);
	}

	static void print(String method, long sum, long time) throws IOException {
		System.out.printf("%32s: %12d  %6d\n", method, sum, time);
	}

	public static void main(String[] args) throws IOException {
		checkInputStream(Paths.get("D:\\Txx728-1"));
		checkBufferedInputStream(Paths.get("D:\\Txx728-2"));
		checkRandomAccessFile(Paths.get("D:\\Txx728-3"));
		checkBufferedRandomAccessFile(Paths.get("D:\\Txx728-4"), 4096);
		checkBufferedRandomAccessFile(Paths.get("D:\\Txx728-5"), 4096 * 2);
		checkMappedFile(Paths.get("D:\\Txx728-6"));
	}
}

实际运行结果:
在这里插入图片描述
说明:为避免系统缓存文件,把一个37M的文件复制多份分别测试。由于 InputStream 和 RandomAccessFile 方法速度太慢, 只读取部分数据进行测试。
从运行数据可以看出

  • InputStream 与 RandomAccessFile 基本相当。
  • BufferedInputStream 要比 InputStream 快两个量级。
  • 操作系统的文件缓存对结果有很大影响。
  • 带缓冲的 RandomAccessFile 与 MappedFile 基本相当。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值