file.length() 和 fileChannel.size()大小不一致

本文探讨了使用file.length()和fileChannel.size()方法测量同一文件大小时出现的显著差异,分析了两种方法的定义,并提出了疑问,寻找导致数值不一致的原因。

今天发现采集的文件大小数据不一致:
对同一个文件,同时采集file.length()和fileChannel.size(),得出的数值不一致并且差距较大。还没找到原因。
在api文件中file.length()解释是:返回由此抽象路径名表示的文件的长度。
fileChannel.size()的解释是:返回此通道文件的当前大小。
所以目前还不清楚为什么

package com.kotei.overseas.navi.update; import java.io.*; import java.nio.channels.FileChannel; import java.util.concurrent.atomic.AtomicLong; public class singlecopydirectory { // 配置参数 private static final int BUFFER_SIZE = 64 * 1024; // 64KB缓冲 private static final long SMALL_FILE_THRESHOLD = 32 * 1024; // 32KB private static final long MEDIUM_FILE_THRESHOLD = 128 * 1024 * 1024; // 128MB private static final long PROGRESS_UPDATE_INTERVAL_MS = 1000; // 1秒更新间隔 public interface BytesProgressCallback { void onProgress(long currentBytes, long totalBytes) throws InterruptedException; } public static boolean copyDirectoryWithProgress(File src, File dest, BytesProgressCallback callback) throws IOException, InterruptedException { // 参数校验 if (!src.isDirectory()) { throw new IllegalArgumentException("Source path must be a directory"); } if (!dest.exists() && !dest.mkdirs()) { throw new IOException("Cannot create destination directory: " + dest.getAbsolutePath()); } // 获取大小 long totalSize = getDirectorySize(src); AtomicLong processedBytes = new AtomicLong(0); long lastUpdateTime = System.currentTimeMillis(); // 执行复制 copyDirectoryInternal(src, dest, processedBytes, callback, totalSize, lastUpdateTime); // 完成回调 if (callback != null) { callback.onProgress(totalSize, totalSize); } return true; } private static void copyDirectoryInternal(File src, File dest, AtomicLong processedBytes, BytesProgressCallback callback, long totalSize, long lastUpdateTime) throws IOException, InterruptedException { File[] files = src.listFiles(); if (files == null) return; for (File file : files) { if (Thread.currentThread().isInterrupted()) { throw new InterruptedException("Copy interrupted"); } File target = new File(dest, file.getName()); if (file.isDirectory()) { if (!target.exists() && !target.mkdirs()) { throw new IOException("Cannot create subdirectory: " + target.getAbsolutePath()); } copyDirectoryInternal(file, target, processedBytes, callback, totalSize, lastUpdateTime); } else { long bytesCopied = copyFileWithProgress(file, target, processedBytes, callback, totalSize, lastUpdateTime); processedBytes.addAndGet(bytesCopied); lastUpdateTime = System.currentTimeMillis(); } } } private static long copyFileWithProgress(File src, File dest, AtomicLong processedBytes, BytesProgressCallback callback, long totalSize, long lastUpdateTime) throws IOException, InterruptedException { long size = src.length(); if (size < SMALL_FILE_THRESHOLD) { return smallFileCopy(src, dest, processedBytes, callback, totalSize, lastUpdateTime); } else if (size < MEDIUM_FILE_THRESHOLD) { long copied = mediumFileCopy(src, dest); updateProgressIfNeeded(processedBytes.get() + copied, totalSize, callback, lastUpdateTime); return copied; } else { long copied = largeFileCopy(src, dest); updateProgressIfNeeded(processedBytes.get() + copied, totalSize, callback, lastUpdateTime); return copied; } } private static long smallFileCopy(File src, File dest, AtomicLong processedBytes, BytesProgressCallback callback, long totalSize, long lastUpdateTime) throws IOException, InterruptedException { try (FileInputStream in = new FileInputStream(src); FileOutputStream out = new FileOutputStream(dest)) { byte[] buffer = new byte[BUFFER_SIZE]; long totalCopied = 0; int n; while ((n = in.read(buffer)) != -1) { out.write(buffer, 0, n); totalCopied += n; updateProgressIfNeeded(processedBytes.get() + totalCopied, totalSize, callback, lastUpdateTime); } return totalCopied; } } private static void updateProgressIfNeeded(long processedBytes, long totalSize, BytesProgressCallback callback, long lastUpdateTime) throws InterruptedException { long currentTime = System.currentTimeMillis(); if (currentTime - lastUpdateTime >= PROGRESS_UPDATE_INTERVAL_MS && callback != null) { callback.onProgress(processedBytes, totalSize); lastUpdateTime = currentTime; } } private static long mediumFileCopy(File src, File dest) throws IOException { try (FileChannel inChannel = new FileInputStream(src).getChannel(); FileChannel outChannel = new FileOutputStream(dest).getChannel()) { return inChannel.transferTo(0, inChannel.size(), outChannel); } } private static long largeFileCopy(File src, File dest) throws IOException { try (FileChannel inChannel = new FileInputStream(src).getChannel(); FileChannel outChannel = new FileOutputStream(dest).getChannel()) { long size = inChannel.size(); long position = 0; long chunkSize = 16 * 1024 * 1024; // 16MB分块 while (position < size) { position += inChannel.transferTo(position, Math.min(chunkSize, size - position), outChannel); } return size; } } private static long getDirectorySize(File dir) { if (dir == null || !dir.exists() || !dir.isDirectory()) { return 0; } long size = 0; File[] files = dir.listFiles(); if (files != null) { for (File file : files) { if (file.isDirectory()) { size += getDirectorySize(file); } else { size += file.length(); } } } return size; } } 这里释放了吗
最新发布
08-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值