分享一个打包的工具

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();
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值