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