0

I have below code where i am trying to create new file in temp directory which is xml file and its working fine.

Now everytime i run the code, i want to delete the previous xml file from this temp directory before creating new xml file because of the size of the xml file is large and it might full my temp space. The xml file has certain naming convention life__*.xml. So it should delete all the life__*.xml files.

I am not sure if we can use tempFile.deleteOnExit() here or how to use that as i am quite new in java file handling and dont know what and where to make change in code:

*/
@Slf4j
public class InputConsumer implements Runnable {

    public static final String XML_SUFFIX = ".xml";

    private void processlifeZipFile() {        //check the number of line in xml input zip file processed
        final AtomicBoolean isInsideLeiRecord = new AtomicBoolean();
        isInsideLeiRecord.set(false);
        final StringBuilder currentLeiRecordXml = new StringBuilder();
        try (FileSystem zipFs = FileSystems.newFileSystem(jobRunner.getInputZipPath(), null);   //check the zip file
             Stream<String> lines = Files.lines(xmlFileFromLeiZipFile(zipFs))) {  //streaming the lines inside xml file
            AtomicInteger processedLinesCounter = new AtomicInteger();
            AtomicInteger currentLineNumber = new AtomicInteger();
            lines
                    .sequential()
                    .forEach(handleLineAndIncrementLineNumber(isInsideLeiRecord, currentLeiRecordXml, processedLinesCounter, currentLineNumber))
            ;
            log.info("{} lines of XML file inside life input ZIP file {} processed.", processedLinesCounter.get(), jobRunner.getInputZipPath() //number of lines processed in xml file
            );
        } catch (IOException e) {
            throw new IllegalStateException("Problem reading input file at " + jobRunner.getInputZipPath() + ".", e);
        }
    }
    private Path xmlFileFromLeiZipFile(FileSystem zipFs) {       //extracts the xml file from zip file
        log.info("Input file {} exists: {}", jobRunner.getInputZipPath(), Files.exists(jobRunner.getInputZipPath()));
        Path tmpXmlPath = createTmpXmlFile("life__" + System.currentTimeMillis());
        for (Path rootDir : zipFs.getRootDirectories()) {
            try (Stream<Path> files = treeAt(rootDir)) {
                log.info("Trying to extract life XML file from ZIP file into {}.", tmpXmlPath);
                final Path xmlFileInsideZip = files
                        .filter(isNotADir())
                        .filter(Files::isRegularFile)
                        .findFirst()
                        .orElseThrow(() -> new IllegalStateException("No file found in LEI ZIP file."));
                log.info("Path to life XML file inside ZIP file: {}.", xmlFileInsideZip);
                return copyReplacing(xmlFileInsideZip, tmpXmlPath);
            }
        }
        throw new IllegalStateException("No file found in LEI ZIP file " + jobRunner.getInputZipPath() + ".");
    }
    

    private static Path createTmpXmlFile(final String prefix) {
        try {
            log.info("Creating temporary file {}{}", prefix, XML_SUFFIX);
            return Files.createTempFile(prefix, XML_SUFFIX);
        } catch (IOException e) {
            throw new IllegalStateException("Could not create tmp file at " + prefix + XML_SUFFIX + ". ", e);
        }
    }
    
    @NotNull
    private static Path copyReplacing(Path from, Path to) {
        requireNonNull(from, "Trying to copy from a path, which is null to path " + to + ".");   //trying to copy file where no xml file exist in root directory
        requireNonNull(to, "Trying to copy from path " + from + " to a path, which is null.");
        try {
            return Files.copy(from, to, REPLACE_EXISTING);
        } catch (IOException e) {
            throw new IllegalStateException("Cannot copy from " + from + " to " + to + ". ", e);
        }
    }
}
Andrew
  • 3,632
  • 24
  • 64
  • 113
  • deleteOnExit only performs the delete when the JVM exits. Create a file object with the path, and call .delete() when you finished the copy. Then return the copy – peterulb Jun 22 '20 at 15:21
  • can you please mentione the code for doing the same ..its really helpful as i was trying the same but not luck yet.. – Andrew Jun 22 '20 at 15:28

1 Answers1

1
Andrew, Please try the below code change done in method processlifeZipFile() and see if it works.

private void processlifeZipFile() {        //check the number of line in xml input zip file processed
        final AtomicBoolean isInsideLeiRecord = new AtomicBoolean();
        isInsideLeiRecord.set(false);
        final StringBuilder currentLeiRecordXml = new StringBuilder();
        Object jobRunner;
        try (FileSystem zipFs = FileSystems.newFileSystem(jobRunner.getInputZipPath(), null);   //check the zip file
                java.nio.file.Path tmpXMLFilePath = xmlFile`enter code here`FromLeiZipFile(zipFs); // Change
             Stream<String> lines = Files.lines(tmpXMLFilePath)) {  //streaming the lines inside xml file
            AtomicInteger processedLinesCounter = new AtomicInteger();
            AtomicInteger currentLineNumber = new AtomicInteger();
            lines
                    .sequential()
                    .forEach(handleLineAndIncrementLineNumber(isInsideLeiRecord, currentLeiRecordXml, processedLinesCounter, currentLineNumber))
            ;
            log.info("{} lines of XML file inside life input ZIP file {} processed.", processedLinesCounter.get(), jobRunner.getInputZipPath() //number of lines processed in xml file
            );
            Files.delete(tmpXMLFilePath); // change
        } catch (IOException e) {
            throw new IllegalStateException("Problem reading input file at " + jobRunner.getInputZipPath() + ".", e);
        }
    }

EDIT ---->

I have created a new method to delete all other files except the new temp xml file.

void deleteXMLFiles(Path xmlPath) {
        try {
            final List<Path> pathsToDelete = Files.list(xmlPath.getParent()).sorted(Comparator.reverseOrder()).collect(Collectors.toList());
            for(Path path : pathsToDelete) {
                if (path.equals(xmlPath)) {
                    System.out.println("Skipping newly created XML file");
                    continue;
                }
                Files.delete(path);
                System.out.println("Deleting -> " + path.toString());
            }
        }catch(IOException ioe) {
            ioe.printStackTrace();
        }
    }

Replace the line "Files.delete(tmpXMLFilePath); // change" with the call to the newly created method with tmpXMLFilePath as the parameter.

deleteXMLFiles(tmpXMLFilePath);

Refer this answer for more details: https://stackoverflow.com/a/47994874/13677537

EDIT 2 ---->

modified the method deleteXMLFiles() to check the file name pattern before deleting :

void deleteXMLFiles(Path xmlPath) {
        try {
            final List<Path> pathsToDelete = Files.list(xmlPath).sorted(Comparator.reverseOrder()).collect(Collectors.toList());
            for (Path path : pathsToDelete) {
                String xmlFileName = path.toString();
                if (Pattern.matches(".*life__.*.xml", xmlFileName)) {
                    Files.delete(path);
                    System.out.println("Deleting -> " + xmlFileName);
                }
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

Modified the processlifeZipFile() method call to delete the temp XML files before creating the new one :

private void processlifeZipFile() {        //check the number of line in xml input zip file processed
        final AtomicBoolean isInsideLeiRecord = new AtomicBoolean();
        isInsideLeiRecord.set(false);
        final StringBuilder currentLeiRecordXml = new StringBuilder();
        
        // Delete the old temp XML Files before starting the processing
        deleteXMLFiles(Paths.get(System.getProperty("java.io.tmpdir")));
        
        try (FileSystem zipFs = FileSystems.newFileSystem(jobRunner.getInputZipPath(), null);   //check the zip file
             Stream<String> lines = Files.lines(xmlFileFromLeiZipFile(zipFs))) {  //streaming the lines inside xml file
            AtomicInteger processedLinesCounter = new AtomicInteger();
            AtomicInteger currentLineNumber = new AtomicInteger();
            lines
                    .sequential()
                    .forEach(handleLineAndIncrementLineNumber(isInsideLeiRecord, currentLeiRecordXml, processedLinesCounter, currentLineNumber))
            ;
            log.info("{} lines of XML file inside life input ZIP file {} processed.", processedLinesCounter.get(), jobRunner.getInputZipPath() //number of lines processed in xml file
            );
        } catch (IOException e) {
            throw new IllegalStateException("Problem reading input file at " + jobRunner.getInputZipPath() + ".", e);
        }
    }
  • Please replace the line "Files.delete(tmpXMLFilePath);" with the below line: "log.info("Temp File Deleted : " + Files.deleteIfExists(tmpXMLFilePath));" and try. – Prashant Rachh Jun 22 '20 at 16:31
  • its deleting the incorrect file actually which is getting created and not all the previous xml files – Andrew Jun 22 '20 at 17:07
  • thanks i am checking now but one question because i want to delete only life__*.xml files because it has been created by this process and i think this logic will delete all *.xml files from tmp directory folder ? – Andrew Jun 23 '20 at 07:55
  • i just tried ...its trying to delete all the other files from temp directory excluding the life__*.xml files – Andrew Jun 23 '20 at 08:11
  • Check the changes given in the EDIT 2 section of the answer – Prashant Rachh Jun 23 '20 at 10:23
  • it will be really helpful if you can help me here: i am using same code but want little bit different logic: https://stackoverflow.com/questions/62537379/file-createtempfile-method-not-working-in-java-and-getting-incompatible-type-err – Andrew Jun 23 '20 at 14:42