javafilefile-exists

Cannot move file because NoSuchFileException


I use this code to list files into directory and move it based on a found value.

    @Override
    public void execute(JobExecutionContext context) {

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

            Path invalidFilesFolderPath = Path.of(directoryPath.getAbsolutePath() + "/invalid_files");
            if (!Files.exists(invalidFilesFolderPath) || !Files.isDirectory(invalidFilesFolderPath)) {
                Files.createDirectory(invalidFilesFolderPath);
            }
        } 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)
                            .withType(CsvLine.class)
                            .withSeparator('\t')
                            .withSkipLines(3)
                            .build()
                            .parse();

                    for (CsvLine item : beans)
                    {
                        Path originalPath = file.toPath();
                        if(item.getValue().equals(2)
                        || item.getValue().equals(43)
                        || item.getValue().equals(32))
                        {
                            // Move here file into new subdirectory when file is invalid
                            Path copied = Paths.get(file.getParent() + "/invalid_files");
                            try {
                                // Use resolve method to keep the "processed" as folder
                                br.close();
                                Files.move(originalPath, copied.resolve(originalPath.getFileName()), StandardCopyOption.REPLACE_EXISTING);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                    }}
            } catch (Exception e){
                e.printStackTrace();
            }
            Path originalPath = file.toPath();
            System.out.println(String.format("\nProcessed file : %s, moving the file to subfolder /processed\n",
                    originalPath));
        }

        // Move here file into new subdirectory when file processing is finished
                            Path copied = Paths.get(file.getParent() + "/processed");
                            try {
                                // Use resolve method to keep the "processed" as folder
                                br.close();
                                Files.move(originalPath, copied.resolve(originalPath.getFileName()), StandardCopyOption.REPLACE_EXISTING);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
    }

The problem is that I try to move a file. I get error:

java.lang.RuntimeException: java.nio.file.NoSuchFileException: C:\csv\nov\12_21_39.csv
      at com.wordscore.engine.processor.DataValidationCheckJob.execute(DataValidationCheckJob.java:94)
      at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
      at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
    Caused by: java.nio.file.NoSuchFileException: C:\csv\nov\12_21_39.csv

How I can edit the code in way that it can be moved properly?


Solution

  • It looks like you have omitted break; after both Files.move(originalPath, ...); calls.

    Without a break to exit the for (CsvLine item : beans) loop, processing continues over the next iteration. The second iteration will attempt to perform Files.move(originalPath, ...) again - and fails because the file has already been moved.

    Therefore you get the NoSuchFileException which you have re-thrown as RuntimeException in your try.. Files.move .. catch block.

    The handling would be cleaner if you dealt with move in one place and such that it avoids the untidy br.close(), leaving file handling to the auto-close try() block. Something like this:

    Path invalidDir = Paths.get(file.getParent() + "/invalid_files");
    Path processedDir = Paths.get(file.getParent() + "/processed");
    for(File file : filesList) {
    
        Path originalPath = file.toPath();
        Path moveTo = processedDir.resolve(originalPath.getFileName());
        
        try (var br = new FileReader(file.getAbsolutePath(), StandardCharsets.UTF_16)){
            List<CsvLine> beans = new CsvToBeanBuilder(br)
                    .withType(CsvLine.class)
                    .withSeparator('\t')
                    .withSkipLines(3)
                    .build()
                    .parse();
    
            for (CsvLine item : beans) {
                if(item.getValue().equals(2)
                || item.getValue().equals(43)
                || item.getValue().equals(32)) {
                    // file is invalid, skip it
                    moveTo = invalidDir.resolve(originalPath.getFileName());
                    // LOG MSG HERE
                    break;
                } 
            }
        }
        Files.move(originalPath, moveTo, StandardCopyOption.REPLACE_EXISTING);
    
        System.out.format("%nProcessed file : %s, moving the file to subfolder %s%n", originalPath, moveTo);
    }