Search code examples
javaxmlfile-handlingtempdir

Delete files before creating new from temp using Java file method


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);
        }
    }
}

Solution

  • 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);
            }
        }