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


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

    对文件的切片/合并在应用中是一个很常见的需求,使用 FileChanneltransferTo / 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/零复制

  • 相关阅读:
    jvm相关参数
    fdisk磁盘分区与挂载
    解决 Redis 只读不可写的问题
    虚拟机linux系统明明已经安装了ubuntu,但是每次重新进入就又是选择安装界面
    linux下更改MySQL数据库存储路径
    消除过期的引用对象
    java避免创建不必要的对象
    Oracle minus用法详解及应用实例
    Mapreduce详解Shuffle过程
    Leet Code 7.整数反转
  • 原文地址:https://www.cnblogs.com/kevinblandy/p/13218490.html
Copyright © 2020-2023  润新知