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;
}
}
这里释放了吗
最新发布