分片讀取文件方法:
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 }