package org.example;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class FileZipperGUI extends Application {
private TextField sourceDirectoryField;
private TextField destinationDirectoryField;
private TextArea logTextArea;
private ProgressBar progressBar;
private ExecutorService executor;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("文件压缩工具");
Label sourceDirectoryLabel = new Label("源目录:");
sourceDirectoryField = new TextField();
sourceDirectoryField.setPrefWidth(300);
Button sourceBrowseButton = new Button("浏览...");
sourceBrowseButton.setOnAction(event -> browseDirectory(primaryStage, sourceDirectoryField));
Label destinationDirectoryLabel = new Label("目标目录:");
destinationDirectoryField = new TextField();
destinationDirectoryField.setPrefWidth(300);
Button destinationBrowseButton = new Button("浏览...");
destinationBrowseButton.setOnAction(event -> browseDirectory(primaryStage, destinationDirectoryField));
Button zipButton = new Button("压缩文件");
zipButton.setOnAction(event -> zipFiles(primaryStage));
logTextArea = new TextArea();
logTextArea.setEditable(false);
logTextArea.setPrefHeight(200);
progressBar = new ProgressBar();
progressBar.setPrefWidth(300);
VBox layout = new VBox(10);
layout.getChildren().addAll(
sourceDirectoryLabel, sourceDirectoryField, sourceBrowseButton,
destinationDirectoryLabel, destinationDirectoryField, destinationBrowseButton,
zipButton, progressBar, logTextArea
);
layout.setPadding(new Insets(10));
Scene scene = new Scene(layout, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
private void browseDirectory(Stage primaryStage, TextField directoryField) {
DirectoryChooser directoryChooser = new DirectoryChooser();
directoryChooser.setTitle("选择目录");
File selectedDirectory = directoryChooser.showDialog(primaryStage);
if (selectedDirectory != null) {
directoryField.setText(selectedDirectory.getAbsolutePath());
}
}
private void zipFiles(Stage primaryStage) {
String sourceDirectoryPath = sourceDirectoryField.getText();
String destinationDirectoryPath = destinationDirectoryField.getText();
File sourceDirectory = new File(sourceDirectoryPath);
File destinationDirectory = new File(destinationDirectoryPath);
if (!sourceDirectory.exists() || !sourceDirectory.isDirectory()) {
log("无效的源目录: " + sourceDirectoryPath);
return;
}
if (!destinationDirectory.exists() || !destinationDirectory.isDirectory()) {
log("无效的目标目录: " + destinationDirectoryPath);
return;
}
File[] files = sourceDirectory.listFiles();
if (files == null || files.length == 0) {
log("目录中未找到文件: " + sourceDirectoryPath);
return;
}
// 创建用于压缩文件的任务
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
Map<String, ZipOutputStream> zipStreams = new HashMap<>();
StringBuilder failedFiles = new StringBuilder();
// 使用固定大小的线程池,有8个线程
executor = Executors.newFixedThreadPool(8);
for (File file : files) {
if (file.isFile()) {
String fileName = file.getName().replaceAll("\\s+", ""); // 从文件名中删除空格
String baseName = getBaseName(fileName);
if (baseName != null) {
// 确保文件可读且未在使用中
if (file.canRead() && !isFileInUse(file)) {
String zipFileName = destinationDirectoryPath + File.separator + baseName + ".zip";
ZipOutputStream zipOutputStream = zipStreams.computeIfAbsent(zipFileName, k -> {
try {
return new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(k)));
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
});
// 将文件写入zip输出流
executor.submit(() -> {
try {
synchronized (zipOutputStream) {
FileInputStream fileInputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
ZipEntry zipEntry = new ZipEntry(fileName);
zipOutputStream.putNextEntry(zipEntry);
byte[] buffer = new byte[8192]; // 根据需要调整缓冲区大小
int bytesRead;
while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
zipOutputStream.write(buffer, 0, bytesRead);
}
bufferedInputStream.close();
zipOutputStream.closeEntry();
fileInputStream.close(); // 写入zip条目后关闭文件输入流
}
} catch (IOException e) {
e.printStackTrace();
failedFiles.append(fileName).append("\n");
}
});
} else {
failedFiles.append(fileName).append("\n");
}
}
}
}
// 当所有任务完成后关闭线程池
executor.shutdown();
// 等待所有任务完成
while (!executor.isTerminated()) {
Thread.sleep(100); // 等待100毫秒
}
// 关闭所有zip输出流
for (ZipOutputStream zipOutputStream : zipStreams.values()) {
try {
zipOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (failedFiles.length() > 0) {
log("以下文件无法压缩:\n" + failedFiles.toString());
} else {
log("文件压缩成功.");
// 显示完成对话框
showCompletionDialog(primaryStage);
}
return null;
}
};
// 将进度条与任务的进度绑定
progressBar.progressProperty().bind(task.progressProperty());
// 处理任务完成
task.setOnSucceeded(event -> {
// 任务完成时解除进度条的绑定
progressBar.progressProperty().unbind();
});
// 处理任务失败
task.setOnFailed(event -> {
// 任务失败时解除进度条的绑定
progressBar.progressProperty().unbind();
});
// 创建线程来执行任务
Thread thread = new Thread(task);
thread.start();
}
private boolean isFileInUse(File file) {
try {
RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.close();
return false;
} catch (IOException e) {
return true;
}
}
private String getBaseName(String fileName) {
int dotIndex = fileName.indexOf('.');
if (dotIndex != -1) {
return fileName.substring(0, dotIndex);
} else {
return null;
}
}
private void log(String message) {
logTextArea.appendText(message + "\n");
}
// 显示完成对话框
private void showCompletionDialog(Stage primaryStage) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("压缩完成");
alert.setHeaderText(null);
alert.setContentText("文件压缩成功!");
alert.initOwner(primaryStage);
alert.showAndWait();
}
@Override
public void stop() {
// 当应用程序停止时关闭线程池
if (executor != null && !executor.isShutdown()) {
executor.shutdownNow();
}
}
}
分享一个打包的工具
猜你喜欢
转载自blog.csdn.net/m0_74173363/article/details/138522242
今日推荐
周排行