package com.example;
import com.example.callback.ProgressCallback;
import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
public class FileUtilszwx {
private static final int THREAD_POOL_SIZE = 4;
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 = 1024 * 1024; // 1MB更新一次进度
// 单线程复制(优化版)
public static boolean copyDirectoryWithProgress(File src, File dest, ProgressCallback callback)
throws IOException, InterruptedException {
if (!src.isDirectory()) {
throw new IllegalArgumentException("源路径必须是目录");
}
if (!dest.exists() && !dest.mkdirs()) {
throw new IOException("无法创建目标目录: " + dest.getAbsolutePath());
}
long totalSize = getDirectorySize(src);
AtomicLong copiedSize = new AtomicLong(0);
long lastUpdateSize = 0;
copyDirectoryInternal(src, dest, totalSize, copiedSize, callback, lastUpdateSize);
if (callback != null) {
callback.onProgress(1000, 1000);
}
return true;
}
private static void copyDirectoryInternal(File src, File dest, long totalSize,
AtomicLong copiedSize, ProgressCallback callback, long lastUpdateSize)
throws IOException, InterruptedException {
File[] files = src.listFiles();
if (files == null) return;
for (File file : files) {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException("复制被中断");
}
File target = new File(dest, file.getName());
if (file.isDirectory()) {
if (!target.exists() && !target.mkdirs()) {
throw new IOException("无法创建子目录: " + target.getAbsolutePath());
}
copyDirectoryInternal(file, target, totalSize, copiedSize, callback, lastUpdateSize);
} else {
long copied = optimizedSmartCopy(file, target);
copiedSize.addAndGet(copied);
// 智能进度更新
long currentCopied = copiedSize.get();
if (currentCopied - lastUpdateSize >= PROGRESS_UPDATE_INTERVAL
|| currentCopied == totalSize) {
updateProgress(currentCopied, totalSize, callback);
lastUpdateSize = currentCopied;
}
}
}
}
// 多线程复制(优化版)
public static boolean copyDirectoryWithProgressMultiThreaded(
File src, File dest, ProgressCallback callback)
throws IOException, InterruptedException {
if (!src.isDirectory()) {
throw new IllegalArgumentException("源路径必须是目录");
}
if (!dest.exists() && !dest.mkdirs()) {
throw new IOException("无法创建目标目录: " + dest.getAbsolutePath());
}
long totalSize = getDirectorySize(src);
if (totalSize == 0) {
System.out.println("源目录为空或大小为0");
return true;
}
AtomicLong copiedSize = new AtomicLong(0);
ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
ExecutorService progressExecutor = Executors.newSingleThreadExecutor();
File[] files = src.listFiles();
if (files == null || files.length == 0) {
executor.shutdown();
progressExecutor.shutdown();
return true;
}
AtomicInteger lastProgress = new AtomicInteger(0);
CountDownLatch latch = new CountDownLatch(files.length);
for (File file : files) {
executor.submit(() -> {
try {
File target = new File(dest, file.getName());
long fileCopied;
if (file.isDirectory()) {
if (!target.exists() && !target.mkdirs()) {
throw new IOException("无法创建子目录: " + target.getAbsolutePath());
}
fileCopied = optimizedCopyDirectory(file, target, totalSize, copiedSize);
} else {
fileCopied = optimizedSmartCopy(file, target);
copiedSize.addAndGet(fileCopied);
}
updateProgress(copiedSize.get(), totalSize, lastProgress, callback, progressExecutor);
} catch (IOException e) {
System.err.println("复制失败: " + file.getName());
e.printStackTrace();
} finally {
latch.countDown();
}
});
}
latch.await();
progressExecutor.submit(() -> {
if (callback != null) {
try {
callback.onProgress(1000, 1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.println("多线程进度: 100.0%");
});
executor.shutdown();
progressExecutor.shutdown();
progressExecutor.awaitTermination(10, TimeUnit.SECONDS);
return true;
}
// 优化的目录复制方法
private static long optimizedCopyDirectory(File src, File dest, long totalSize, AtomicLong copiedSize)
throws IOException {
long copied = 0;
File[] files = src.listFiles();
if (files == null) return 0;
for (File file : files) {
File target = new File(dest, file.getName());
if (file.isDirectory()) {
if (!target.exists() && !target.mkdirs()) {
throw new IOException("无法创建子目录: " + target.getAbsolutePath());
}
copied += optimizedCopyDirectory(file, target, totalSize, copiedSize);
} else {
long fileCopied = optimizedSmartCopy(file, target);
copied += fileCopied;
copiedSize.addAndGet(fileCopied);
}
}
return copied;
}
// 优化的智能复制方法
private static long optimizedSmartCopy(File src, File dest) throws IOException {
long size = src.length();
if (size < SMALL_FILE_THRESHOLD) {
return smallFileCopy(src, dest);
} else if (size < MEDIUM_FILE_THRESHOLD) {
return mediumFileCopy(src, dest);
} else {
return largeFileCopy(src, dest);
}
}
// 小文件复制(缓冲方式)
private static long smallFileCopy(File src, File dest) throws IOException {
try (FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dest)) {
byte[] buffer = new byte[BUFFER_SIZE];
long total = 0;
int n;
while ((n = in.read(buffer)) != -1) {
out.write(buffer, 0, n);
total += n;
}
return total;
}
}
// 中等文件复制(transferTo)
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);
}
}
// 大文件复制(分块transferTo)
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) {
long remaining = size - position;
long transferSize = Math.min(chunkSize, remaining);
position += inChannel.transferTo(position, transferSize, outChannel);
}
return size;
}
}
// 保持原有的进度更新方法不变
private static void updateProgress(long currentCopied, long totalSize,
ProgressCallback callback) {
// 原有实现保持不变
}
private static void updateProgress(long currentCopied, long totalSize,
AtomicInteger lastProgress, ProgressCallback callback,
ExecutorService progressExecutor) {
// 原有实现保持不变
}
// 优化的目录大小计算
public 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;
}
}
[INFO] --- exec-maven-plugin:3.5.0:java (default-cli) @ compress-benchmark ---
/home/zhouweixiang/test/git/S32-GIT-DOWNLOAD
true
true
=== 单线程复制开始 ===
单线程进度: 1000%
单线程复制完成,耗时: 240352 ms,结果: true
目前没有任何进度打印在命令行请你解决,并且目前9gb文件夹复制花费4分钟