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


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

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

  • 相关阅读:
    Python入门_绘制多个五角形_turtle
    Selenium3+python自动化6-八种元素元素定位(Firebug和firepath)
    MongoDB入门(3)- MongoDB备份与恢复
    MongoDB入门(2)- MongoDB安装
    MongoDB入门(1)- MongoDB简介
    Elastic Search操作入门
    应用Xml.Linq读xml文件
    Struts2入门(1)-第一个Struts2程序
    Hibernate入门(4)- Hibernate数据操作
    Hibernate入门(3)- 持久对象的生命周期介绍
  • 原文地址:https://www.cnblogs.com/kevinblandy/p/13218490.html
Copyright © 2020-2023  润新知