Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Unable to delete file after using SevenZip.openArchive method in java

In my endpoint I receive the content of a file as String in format base64.
Unzipping works fine with SevenZip library, no problems there.
But after executing this line

archive = SevenZip.openInArchive(null, new RandomAccessFileInStream(
                        new RandomAccessFile(file, "r")));

java is unable to delete file because of following exception:

java.nio.file.FileSystemException: myFile.RAR: The process cannot access the file because it is being used by another process

I have tried to use junrar library, but SevenZip works better (supports RAR5 and identifies less corupted files as junrar).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>demo</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>

        <dependency>
            <groupId>net.sf.sevenzipjbinding</groupId>
            <artifactId>sevenzipjbinding</artifactId>
            <version>16.02-2.01</version>
        </dependency>
        <dependency>
            <groupId>net.sf.sevenzipjbinding</groupId>
            <artifactId>sevenzipjbinding-all-platforms</artifactId>
            <version>16.02-2.01</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Here is the dto:

public record UploadDto(
        @NotNull
        String name,
        @NotNull
        String data) {
}

Here is the controller with the logic:

import net.sf.sevenzipjbinding.IInArchive;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;

@RestController
public class TestController {
    private final Logger log = LoggerFactory.getLogger(TestController.class);

    @PostMapping("/upload")
    public void extractRar(@RequestBody UploadDto dto){
        byte[] decodedBytes = Base64.getDecoder().decode(dto.data());
        try {
            String filePath = dto.name();
            Files.write(Paths.get(filePath), decodedBytes);
            log.info("File saved successfully to: " + filePath);
            File file = new File(filePath);
            IInArchive archive;
            try {
                archive = SevenZip.openInArchive(null, new RandomAccessFileInStream(
                        new RandomAccessFile(file, "r")));
                log.info(String.valueOf(archive.getNumberOfItems()));
            } catch (SevenZipException | FileNotFoundException e) {
                throw new RuntimeException(e);
            }
            archive.close();

            // 1 method
            Files.delete(Path.of(filePath));

            // 2 method
            if (file.delete()) {
                log.info("file deleted successfully");
            } else {
                log.error("failed to delete the temporary file used for unzipping");
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

example of request body :

{
  "name": "myFile.RAR",
  "data": "UmFyIRoHAM+QcwAADQAAAAAAAABTL3QgkC8AFAAAABQAAAACTeXQiWmKL1cdMAoAIAAAAG15RmlsZS50eHQAsAA/PXJhciBkYXRhIG1vY2sgaGVyZQ0KxD17AEAHAA=="
}

I have tried 2 methods to delete the file, but none of them seems to work.
Also I didn’t find any method to openArchive using a byte array or InputStream.
The problem would be solved if I could delete the file after extracting the content or to extract the content without saving the file locally.
Any help or ideas would be appreciated!
OS windows 10

>Solution :

Examples found online, close the file after closing the archive.

Something like the following (depending on your needs, you may want to try-catch the close() calls separately) :

@PostMapping("/upload")
public void extractRar(@RequestBody UploadDto dto){
    byte[] decodedBytes = Base64.getDecoder().decode(dto.data());
    try {
        String filePath = dto.name();
        Files.write(Paths.get(filePath), decodedBytes);
        log.info("File saved successfully to: " + filePath);
        File file = new File(filePath);
        IInArchive archive;
        RandomAccessFile randomAccessFile;
        try {
            
            randomAccessFile = new RandomAccessFile(file, "r");
            archive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile));
            log.info(String.valueOf(archive.getNumberOfItems()));
        } catch (SevenZipException | FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        archive.close();
        randomAccessFile.close();

        // 1 method
        Files.delete(Path.of(filePath));

        // 2 method
        if (file.delete()) {
            log.info("file deleted successfully");
        } else {
            log.error("failed to delete the temporary file used for unzipping");
        }

    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading