分片读取文件方法:
/**
* 分片读取文件块
*
* @param path 文件路径
* @param position 角标
* @param blockSize 文件块大小
* @return 文件块内容
*/
public static byte[] read(String path, long position, int blockSize) throws Exception {
// ----- 校验文件,当文件不存在时,抛出文件不存在异常
checkFilePath(path, false);
// ----- 读取文件
ByteBuffer block = ByteBuffer.allocate(blockSize);
try (AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get(path), StandardOpenOption.READ)) {
Future<Integer> read = channel.read(block, position);
while (!read.isDone()) {
// ----- 睡1毫秒, 不抢占资源
Thread.sleep(1L);
}
}
return block.array();
}
分片写文件方法:
/**
* 分片写文件
*
* @param path 文件目标位置
* @param block 文件块内容
* @param position 角标
* @throws Exception
*/
public static void write(String path, byte[] block, long position) throws Exception {
// ----- 校验文件,当文件不存在时,创建新文件
checkFilePath(path, true);
// ----- 写文件
ByteBuffer buffer = ByteBuffer.wrap(block);
try (AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get(path), StandardOpenOption.WRITE)) {
Future<Integer> write = channel.write(buffer, position);
while (!write.isDone()) {
// ----- 睡1毫秒, 不抢占资源
Thread.sleep(1L);
}
}
}
检查文件是否存在方法:
/**
* 校验文件
*
* @param path 文件路径
* @param flag 当文件不存在时是否创建文件 [true: 创建文件;false: 抛出文件不存在异常]
* @return
* @throws Exception
*/
public static File checkFilePath(String path, boolean flag) throws Exception {
if (StringUtils.isBlank(path)) {
throw new RuntimeException("The file path cannot be empty.");
}
File file = new File(path);
if (!file.exists()) {
if (flag) {
// ----- 当文件不存在时,创建新文件
if (!file.createNewFile()) {
throw new RuntimeException("Failed to create file.");
}
} else {
// ----- 抛出文件不存在异常
throw new RuntimeException("File does not exist.");
}
}
return file;
}
测试:
/*** 分片读写文件的每片默认大小: 10M */
private static final Integer DEFAULT_BLOCK_SIZE = 1024 * 1024 * 10;
public static void main(String[] args) throws Exception {
String path = "F:\\compression\\Spring源码深度解析.pdf";
String toPath = "F:\\compression\\" + System.currentTimeMillis() + ".pdf";
File file = FileUtil.checkFilePath(path, false);
long position = 0, length = file.length();
while (length > DEFAULT_BLOCK_SIZE) {
// ----- 如果文件大小大于默认分块大小,循环读写文件,每次循环读取一块,直到剩余文件大小小于默认分块大小
byte[] block = FileUtil.read(path, position, DEFAULT_BLOCK_SIZE);
FileUtil.write(toPath, block, position);
position += DEFAULT_BLOCK_SIZE;
length -= DEFAULT_BLOCK_SIZE;
}
if (length > 0) {
// ----- 如果文件大小小于默认分块大小且大于零,正常读写文件
byte[] block = FileUtil.read(path, position, (int) length);
FileUtil.write(toPath, block, position);
}
}