【问题标题】:Move file after reading content读取内容后移动文件
【发布时间】:2022-11-19 11:41:56
【问题描述】:

我想创建一个 Quartz 作业,它读取 .csv 文件并在处理文件时移动它们。我试过这个:

@Override
public void execute(JobExecutionContext context) {

    File directoryPath = new File("C:\\csv\\nov");
    // Create a new subfolder called "processed" into source directory
    try {
        Files.createDirectory(Path.of(directoryPath.getAbsolutePath() + "/processed"));
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

    FilenameFilter textFileFilter = (dir, name) -> {
        String lowercaseName = name.toLowerCase();
        if (lowercaseName.endsWith(".csv")) {
            return true;
        } else {
            return false;
        }
    };
    // List of all the csv files
    File filesList[] = directoryPath.listFiles(textFileFilter);
    System.out.println("List of the text files in the specified directory:");
    for(File file : filesList) {

        try {
            List<CsvLine> beans = new CsvToBeanBuilder(new FileReader(file.getAbsolutePath(), StandardCharsets.UTF_16))
                    .....
                    .build()
                    .parse();

            for(CsvLine item: beans){

                    ....... sql queries

                    Optional<ProcessedWords> isFound = processedWordsService.findByKeyword(item.getKeyword());

                    ......................................
            }

        } catch (Exception e){
            e.printStackTrace();
        }

        // Move here file into new subdirectory when file processing is finished
        Path copied = Paths.get(file.getAbsolutePath() + "/processed");
        Path originalPath = file.toPath();
        try {
            Files.move(originalPath, copied, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

文件夹 processed 是在作业启动时创建的,但出现异常:

    org.quartz.SchedulerException: Job threw an unhandled exception.
        at org.quartz.core.JobRunShell.run(JobRunShell.java:213) ~[quartz-2.3.2.jar:na]
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) ~[quartz-2.3.2.jar:na]
    Caused by: java.lang.RuntimeException: java.nio.file.FileSystemException: C:\csv\nov\07_06_26.csv -> C:\csv\nov\07_06_26.csv\processed: The process cannot access the file because it is being used by another process
        at com.wordscore.engine.processor.ImportCsvFilePostJob.execute(ImportCsvFilePostJob.java:114) ~[main/:na]
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.3.2.jar:na]
        ... 1 common frames omitted
    Caused by: java.nio.file.FileSystemException: C:\csv\nov\07_06_26.csv -> C:\csv\nov\

07_06_26.csv\processed: The process cannot access the file because it is being used by another process
    at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:92) ~[na:na]
    at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103) ~[na:na]

你知道我如何释放文件并将其移动到子目录中吗?

编辑:使用 try-catch 更新代码

@Override
public void execute(JobExecutionContext context) {

    File directoryPath = new File("C:\\csv\\nov");
    // Create a new subfolder called "processed" into source directory
    try {
        Path path = Path.of(directoryPath.getAbsolutePath() + "/processed");
        if (!Files.exists(path) || !Files.isDirectory(path)) {
            Files.createDirectory(path);
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

    FilenameFilter textFileFilter = (dir, name) -> {
        String lowercaseName = name.toLowerCase();
        if (lowercaseName.endsWith(".csv")) {
            return true;
        } else {
            return false;
        }
    };
    // List of all the csv files
    File filesList[] = directoryPath.listFiles(textFileFilter);
    System.out.println("List of the text files in the specified directory:");
    for(File file : filesList) {

        try {
            try (var br = new FileReader(file.getAbsolutePath(), StandardCharsets.UTF_16)){
                List<CsvLine> beans = new CsvToBeanBuilder(br)
                        ......
                        .build()
                        .parse();

            for (CsvLine item : beans) {

                .....
                if (isFound.isPresent()) {
                    .........
        }}

        } catch (Exception e){
            e.printStackTrace();
        }

        // Move here file into new subdirectory when file processing is finished
        Path copied = Paths.get(file.getAbsolutePath() + "/processed");
        Path originalPath = file.toPath();
        try {
            Files.move(originalPath, copied, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

【问题讨论】:

    标签: java opencsv


    【解决方案1】:
    new FileReader(file.getAbsolutePath(), StandardCharsets.UTF_16)
    

    这部分创建一个资源.资源是代表底层重物的对象——你可以拥有的东西很少。在这种情况下,它表示底层操作系统文件句柄。

    您必须始终安全地关闭这些.实际上只有两种方法可以正确地做到这一点:

    • 使用 try-with-resources
    • 将其保存到一个字段中,并使自己成为AutoClosable,以便使用此类实例的代码可以使用 try-with-resources
    try (var br = new FileReader(file, StandardCharsets.UTF_16)) {
      List<CsvLine> beans = new CsvToBeanBuilder(br)
                        .....
                        .build()
                        .parse();
    }
    

    是答案。

    【讨论】:

    • 我更新了我的代码以使用 try-catch 但我仍然收到错误。看起来我需要在处理结束时手动关闭文件。你能告诉我这是如何实现的吗?
    • 您需要更新代码以使用 try-with,正如我在 sn-p 中展示的那样; catch 与它无关。试用将要一旦代码流退出伴随它的大括号就关闭资源——不管它是如何退出的(运行到最后,return;break;,抛出异常——不管)。就是这个。如果您仍然遇到此错误,可能是 [A] 您计算机上的另一个进程打开了它,或者 [B] 您没有按照我说的去做。
    • 听起来像另一个进程(或您没有应用 try-with 或没有关闭资源的其他代码)也打开了该文件。您不能从您的应用程序中强制关闭其他应用程序。
    • 我测试了这个基本的 JUnit 测试,只是为了确保其他进程没有锁定文件:pastebin.com/KsWkysyF 我遇到了同样的错误。还有其他想法吗?
    猜你喜欢
    • 2020-08-23
    • 2019-08-02
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-21
    • 1970-01-01
    相关资源
    最近更新 更多