Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return Zip File from ZipOutputStream in Java

I have a function which creates a Zip file from a list of files. Is it possible to return the Zip file without it being saved on the disk? I need the file as I have to use the zip file as a parameter for another function. I am not sure of the ByteStream would be an option for me.

public File compressFileList(List<File> fileList,String fileName) {
    FileOutputStream fileOutputStream=null;
    ZipOutputStream zipOutputStream=null;
    FileInputStream fileInputStream=null;
    String compressedFileName=fileName +".zip";
    if(fileList.isEmpty())
        return null;
    try
    {
        fileOutputStream =  new FileOutputStream(compressedFileName);
        zipOutputStream = new ZipOutputStream(new BufferedOutputStream(fileOutputStream));
        for (File file: fileList) {
            fileInputStream = new FileInputStream(file);
            ZipEntry zipEntry =  new ZipEntry(file.getName());
            zipOutputStream.putNextEntry(zipEntry);
            byte[] tmp = new byte[4*1024];
            int size = 0;
            while((size = fileInputStream.read(tmp)) != -1){
                zipOutputStream.write(tmp, 0, size);
            }
            zipOutputStream.flush();
            fileInputStream.close();
        }
        zipOutputStream.close();
        return compressedFile; //This is what I am missing

    }
    catch (FileNotFoundException e)
    {

    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

EDIT : adding the use case

The idea is to create a zip file and use the CreateClassifierOptions method of VisualRecognition Service of Watson.

classifierOptions = new CreateClassifierOptions.Builder()
            .classifierName("Santa")
            .addClass("Santa", new File("C:\\app\\GitRepo\\images\\beagle.zip"))
            .negativeExamples(new File("C:\\app\\GitRepo\\images\\nosport.zip"))
            .build();

The builder accepts the zip file as the parameter.

Understanding

Based on the explanation from Alexandre Dupriez, I think it is better to store the file at some place on the hard disk.

like image 986
Vini Avatar asked Nov 25 '25 22:11

Vini


1 Answers

You should be able to use a ByteArrayOutputStream instead of a FileOutputStream:

zipOutputStream = new ZipOutputStream(new ByteArrayOutputStream());

The difficulty here is to provide a File to the method consuming the zip file. The java.io.File does not provide an abstraction which allows you to manipulate in-memory files.

The java.io.File abstraction and java.io.FileInputStream implementation

To simplify, if we had to boil down what the File abstraction is, we would see it as a URI. And therefore, to be able to build an in-memory File, or at least mimic it, we would need to provide an URI which would then be used by the consumer of the File to read its content.

If we look at the FileInputStream which the consumer is likely to use, we can see that it always ends up with a native call which gives us to possibility whatsoever to abstract a FileSystem for in-memory files:

// class java.io.FileInputStream
/**
 * Opens the specified file for reading.
 * @param name the name of the file
 */
private native void open0(String name) throws FileNotFoundException;

It would be easier if there was a possibility to adapt the consumer to accept an InputStream, but from your problem statement I guess this is not possible.

API call

Your requirement is to provide a File to the Watson Visual API. Could you please provide the API method you need to call?

like image 90
Alexandre Dupriez Avatar answered Nov 27 '25 12:11

Alexandre Dupriez



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!