当前位置: 首页 > 知识库问答 >
问题:

如何设计我的JavaFX服务/任务来计算文件的4个校验和?

陈坚
2023-03-14

我是JavaFX新手,对软件的设计/架构有问题。

我的用例是:

  1. 用户通过文件选择器或每次拖动将文件插入到我的软件中

目前我只计算一个校验和,因为我不知道如何等待其他服务。我觉得我的设计不是很聪明。你有什么建议吗?

dev.kanka.checksumsharer.ChecksumSharerApplication#handleDragAndDropFiles

private void handleDragAndDropFiles(Dragboard dragboard) {
    List<File> newFiles = dragboard.getFiles();
    logger.info("Dropped files: " + newFiles);
    FileUtil.handleNewFiles(newFiles);
}

dev.kanka。查克沙勒。乌提尔斯。FileUtil#handleNewFiles

public static void handleNewFiles(List<File> files) {
    for (java.io.File file : files) {
        KnkFile knkFile = new KnkFile(file.getAbsolutePath());

        ChecksumCalculatorService sha256service = new ChecksumCalculatorService(knkFile, Algorithm.SHA_256);
        sha256service.start();
        sha256service.setOnSucceeded(event -> {
            knkFile.setSha256(sha256service.getValue());
            logger.debug(knkFile);
            // TODO: I could call the second service here?
            FileDAO.insertFile(knkFile);
        });



//      ChecksumCalculatorService sha512Service = new ChecksumCalculatorService(file, Algorithm.SHA_512);
//      ChecksumCalculatorService sha3384Service = new ChecksumCalculatorService(file, Algorithm.SHA3_384);
//      ChecksumCalculatorService sha3512Service = new ChecksumCalculatorService(file, Algorithm.SHA3_512);
//
//      sha512Service.start();
//      sha3384Service.start();
//      sha3512Service.start();

    // TODO: How can I insert this one file after calculating all checksums? Software Architecture Question...

    }
}

检查和计算器服务:

package dev.kanka.checksumsharer.hash;

import dev.kanka.checksumsharer.models.KnkFile;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class ChecksumCalculatorService extends Service<String> {

    private static final Logger logger = LogManager.getLogger();

    private KnkFile knkFile;
    private Algorithm algorithm;

    public ChecksumCalculatorService(KnkFile f, Algorithm algorithm) {
        this.knkFile = f;
        this.algorithm = algorithm;
    }

    private String getChecksumOfFile() throws IOException, NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance(algorithm.toString());

        // Get knkFile input stream for reading the knkFile content
        try (FileInputStream fis = new FileInputStream(this.knkFile)) {
            // Create byte array to read data in chunks
            byte[] byteArray = new byte[8192];
            int bytesCount = 0;

            // Read knkFile data and update in message digest
            while ((bytesCount = fis.read(byteArray)) != -1) {
                digest.update(byteArray, 0, bytesCount);
            }
        }

        //Get the hash's bytes
        byte[] bytes = digest.digest();

        // bytes[] has bytes in decimal format;
        // Convert it to hexadecimal format
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
        }

        return sb.toString();
    }

    @Override
    protected Task<String> createTask() {
        return new Task<>() {
            @Override
            protected String call() throws Exception {
                return getChecksumOfFile();
            }
        };
    }
}

创建4个服务可以吗?或者我可以创建一个包含4个任务的服务吗?在将信息插入数据库之前,如何同步它们并等待所有结果?

谢谢

我试着跟着回答。

public class ChecksumCalculationTask extends Task<String> {

    private static final Logger logger = LogManager.getLogger();

    private final KnkFile knkFile;
    private final Algorithm algorithm;

    public ChecksumCalculationTask(KnkFile f, Algorithm algorithm) {
        this.knkFile = f;
        this.algorithm = algorithm;
    }

    private String getChecksumOfFile() throws IOException, NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance(algorithm.toString());

        // Get knkFile input stream for reading the knkFile content
        try (FileInputStream fis = new FileInputStream(this.knkFile)) {
            // Create byte array to read data in chunks
            byte[] byteArray = new byte[8192];
            int bytesCount = 0;

            // Read knkFile data and update in message digest
            while ((bytesCount = fis.read(byteArray)) != -1) {
                digest.update(byteArray, 0, bytesCount);
            }
        }

        //Get the hash's bytes
        byte[] bytes = digest.digest();

        // bytes[] has bytes in decimal format;
        // Convert it to hexadecimal format
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
        }

        return sb.toString();
    }

    public KnkFile getKnkFile() {
        return this.knkFile;
    }

    public Algorithm getAlgorithm() {
        return this.algorithm;
    }

    @Override
    protected String call() throws Exception {
        return getChecksumOfFile();
    }
}

dev.kanka。查克沙勒。乌提尔斯。FileUtil#handleNewFiles

public static void handleNewFiles(List<File> files) {
        ExecutorService exec = Executors.newFixedThreadPool(Algorithm.values().length);
        List<ChecksumCalculationTask> tasks = new ArrayList<>();

        for (File file : files) {
            KnkFile knkFile = new KnkFile(file.getAbsolutePath());

            tasks.add(new ChecksumCalculationTask(knkFile, Algorithm.SHA_256));
            tasks.add(new ChecksumCalculationTask(knkFile, Algorithm.SHA_512));
            tasks.add(new ChecksumCalculationTask(knkFile, Algorithm.SHA3_384));
            tasks.add(new ChecksumCalculationTask(knkFile, Algorithm.SHA3_512));
        }

        List<Future<String>> futures = exec.invokeAll(tasks);

        // Create a `Task` that waits until they're finished and processes them all
        Task<Void> processCompletedTasks = new Task<>() {
            @Override
            protected Void call() throws Exception {
                // block until tasks complete
                for (Future<String> f : futures) {
                    f.get();
                }
                // process completed tasks
                for (ChecksumCalculationTask task : tasks) {
                    KnkFile knkFile = task.getKnkFile();
                    String checksum = task.getValue();
                    Algorithm algorithm = task.getAlgorithm();

                    // ... whatever you need here, note this is on background thread
                }
                return null;
            }
        };
        exec.submit(processCompletedTasks);
        exec.shutdown();
    }

对我来说,这看起来很有逻辑,但我在IntelliJ中遇到了一个编译器错误,因为exec.invokeAll-call:原因:没有类型变量T的实例存在,因此Checksum计算任务符合Callable


共有1个答案

邵星光
2023-03-14

将校验和计算器设置为任务,而不是服务

public class ChecksumCalculatorTask extends Task<String> {

    private static final Logger logger = LogManager.getLogger();

    private final KnkFile knkFile;
    private final Algorithm algorithm;

    public ChecksumCalculatorService(KnkFile f, Algorithm algorithm) {
        this.knkFile = f;
        this.algorithm = algorithm;
    }

    public KnkFile getKnkFile() {
        return knkFile;
    }

    private String getChecksumOfFile() throws IOException, NoSuchAlgorithmException {

        // ...

    }

    @Override
    protected String call() throws Exception {
        return getChecksumOfFile();
    }
}

创建执行者:

private ExecutorService exec = Executors.newCachedTheadPool() ;

现在,您可以将任务提交给执行者:

public static void handleNewFiles(List<File> files) {

    List<ChecksumCalculatorTask> tasks = new ArrayList<>();

    for (java.io.File file : files) {
        KnkFile knkFile = new KnkFile(file.getAbsolutePath());

        ChecksumCalculatorTask sha256task = new ChecksumCalculatorTask(knkFile, Algorithm.SHA_256);
        tasks.add(sha256Task);
        sha256task.setOnSucceeded(event -> {
            logger.debug(knkFile);
        });
    }

    // And now you can invoke all the tasks:

    List<Future<String>> futures = exec.invokeAll(tasks);

    // Create a `Task` that waits until they're finished and processes tham all:

    Task<Void> processCompletedTasks = new Task<>() {
        @Override
        protected Void call() throws Exception {
            // block until tasks complete:
            for (Future<String> f : futures) {
                f.get();
            }
            // process completed tasks:
            for (ChecksumCalculatorTask task : tasks) {
                KnkFile file = task.getKnkFile() ;
                String checksum = task.getValue();
                // ... whatever you need here, note this is on background thread
            }
        }
    };
    exec.submit(processCompletedTasks);
}
 类似资料:
  • 我正在使用iTextSharp从PDF文件中读取文本。然而,有些时候我不能提取文本,因为PDF文件只包含图像。我每天下载同样的PDF文件,我想看看PDF是否被修改过。如果无法获得文本和修改日期,那么MD5校验和是判断文件是否已更改的最可靠方法吗? 如果是的话,一些代码示例将会很感激,因为我对密码学没有太多的经验。

  • 我一直在阅读有关为将向客户公开的REST服务设计API的最佳实践。例如,我们应该使用名词来命名所有公开的URI。此外,动词应遵循HTTP命令的语义。例如,GET请求不应该修改资源,而应该在这里使用PUT请求。我在一次采访中被问到这个问题,但我不能满意地回答这个问题——我正在设计一个计算器,它提供以下功能:对两个操作数进行加法、乘法、除法和减法。如何按照REST原则向客户端公开这些方法。这些操作要使

  • 在此之前我问了一个问题。我的服务conifg是: 我编写了一个扩展mediator交易文件。该类返回文件名并向服务发送请求。服务没有输入消息。我要每天13:30的服务。我尝试添加新的计划任务。但是它不能工作?谁能告诉我如何设置这个计划任务? 我也不知道如何设置“固定服务器”。

  • 问题内容: 我正在为大型视频文件创建MD5校验和。我当前正在使用代码: 但这会创建一个内存缓冲区,并且对于大型视频文件而言并不理想。Swift中是否有一种方法可以计算读取文件流的MD5校验和,从而使内存占用量最小? 问题答案: 您可以分块计算MD5校验和,例如在?中有没有一个MD5库不需要同时输入全部内容?。 这是使用Swift的可能实现(现已针对Swift 5更新) 需要自动释放池来释放所返回的

  • 服务端设计 服务端主要的问题是大数据的实时处理,截止2017年6月后端CAT的计算集群大约100台物理机,存储集群大约50台物理机,每天处理了约200TB的数据量。下面是CAT服务端一些设计细节: 架构设计 服务端单机cat-consumer的整体架构如下: 如上图,CAT服务端在整个实时处理中,基本上实现了全异步化处理。 消息接收是基于Netty的NIO实现 消息接收到服务端就存放内存队列,然后