-2

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?

Peter Penzov
  • 1,126
  • 134
  • 430
  • 808

1 Answers1

1

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);
}
DuncG
  • 12,137
  • 2
  • 21
  • 33
  • Can you paste the full code here, please? – Peter Penzov Feb 04 '23 at 10:03
  • Add `break;` after each `Files.move(originalPath, ...);` – DuncG Feb 04 '23 at 10:05
  • I have one idea. is it possible to move the functionality for `Files.move(originalPath, ...);` outside of the loop `for (CsvLine item : beans)` and use Boolean flag to indicate to which directory at the end the file should be moved? – Peter Penzov Feb 04 '23 at 10:13
  • Correct - had added a outline which means only one `Files.move`. – DuncG Feb 04 '23 at 10:56
  • I found one issue into the code. See the original post. Notice that if we find a value 32 for example the file will be moved which is correct. But after moving the file we want to continue with next file. I placed the code responsible for moving the file at the folder `/processes` at the end because in every way when the file is processed we want to move the file to `/processes` directory but I get again `Caused by: java.nio.file.NoSuchFileException` any idea how to fix this? – Peter Penzov Feb 04 '23 at 15:29
  • Your code above shows that a file with value 32 is moved to invalid, so if you try to move it to processed afterwards of course you will get `NoSuchFileException`. Perhaps you intend just to `Files.copy` to "invalid", and `Files.move` to "processed"? – DuncG Feb 04 '23 at 16:25