文件切片 Java_使用零拷贝对文件高效的切片和合并

对文件的切片/合并在应用中是一个很常见的需求,使用 FileChannel的 transferTo / transferFrom 的零拷贝方法(需要操作系统支持),可以高效的完成。

切片

/**

* 对文件按照指定大小进行分片,在文件所在目录生成分片后的文件块儿

* @param file

* @param chunkSize

* @throws IOException

*/

public static void chunkFile(Path file, long chunkSize) throws IOException {

if (Files.notExists(file) || Files.isDirectory(file)) {

throw new IllegalArgumentException("文件不存在:" + file);

}

if (chunkSize < 1) {

throw new IllegalArgumentException("分片大小不能小于1个字节:" + chunkSize);

}

// 原始文件大小

final long fileSize = Files.size(file);

// 分片数量

final long numberOfChunk = fileSize % chunkSize == 0 ? fileSize / chunkSize : (fileSize / chunkSize) + 1;

// 原始文件名称

final String fileName = file.getFileName().toString();

// 读取原始文件

try(FileChannel fileChannel = FileChannel.open(file, EnumSet.of(StandardOpenOption.READ))){

for (int i = 0; i < numberOfChunk; i++) {

long start = i * chunkSize;

long end = start + chunkSize;

if (end > fileSize) {

end = fileSize;

}

// 分片文件名称

Path chunkFile = Paths.get(fileName + "-" + (i + 1));

try (FileChannel chunkFileChannel = FileChannel.open(file.resolveSibling(chunkFile),

EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE))){

// 返回写入的数据长度

fileChannel.transferTo(start, end - start, chunkFileChannel);

}

}

}

}

组合

/**

* 把多个文件合并为一个文件

* @param file目标文件

* @param chunkFiles分片文件

* @throws IOException

*/

public static void mergeFile (Path file, Path ... chunkFiles) throws IOException {

if (chunkFiles == null || chunkFiles.length == 0) {

throw new IllegalArgumentException("分片文件不能为空");

}

try (FileChannel fileChannel = FileChannel.open(file, EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE))){

for (Path chunkFile : chunkFiles) {

try(FileChannel chunkChannel = FileChannel.open(chunkFile, EnumSet.of(StandardOpenOption.READ))){

chunkChannel.transferTo(0, chunkChannel.size(), fileChannel);

}

}

}

}

最后

零拷贝

https://zh.wikipedia.org/zh-hans/零复制


版权声明:本文为weixin_32768455原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。