Search code examples
javagroovyzip

Groovy delete original file after zip file creation


I am looking for a way to create a zip file at the same location as the file I am creating a zip archive for. And then want to want to delete the original file.

I want to know what would be the best approach to do this? This is what I have tried:

import java.util.zip.*

class ZipUtility {

    def createZipFile(fileToZip, cleanUp=False){
        String zipFileName = fileToZip.toString() + ".zip"
        ZipOutputStream zipFile = new ZipOutputStream(new FileOutputStream(zipFileName))
        if (fileToZip.isFile()) {
            zipFile.putNextEntry(new ZipEntry(fileToZip.name))
            def buffer = new byte[fileToZip.size()]
            fileToZip.withInputStream {
                zipFile.write(buffer, 0, it.read(buffer))
            }
            zipFile.closeEntry()
        }
        zipFile.close()

        if (cleanUp) {
            // this deletes the file test.txt
            boolean fileSuccessfullyDeleted =  new File(fileToZip).delete()
        }
        return zipFile // Not sure if this is the correct approach. Any Exceptions to look for?
  }

I come from a Python background, and my knowledge in groovy/ java is limited.


Solution

  • Generally you wrote it correctly. Only some minor tweaks to take advantage of Groovy things. One is only create and return the zip file if the fileToZip is an actual file. You could make it handle directories too, but that's a different story.

    Boolean literal False is false in Java/Groovy.

    Use withCloseable and your stream will be closed when the closure finishes regardless of exception or successful operation.

    You were reading the full file into memory which you don't have to do, and it'll put an upper bound on the size of the file you could perform the operation on. Instead using the << operator it'll handle reading the Inputstream into an OutputStream without the messy details of allocating bytes and reading it fully into memory thus enabling any size file to be used.

    Finally, moved the fileToZip.delete call inside the if statement and after we've created the zip file where we know it's safe to delete it.

    import java.util.zip.*
    
    class ZipUtility {
    
        File createZipFile(File fileToZip, boolean cleanUp=false) {
            String zipFileName = "${fileToZip.name}.zip"
            if (fileToZip.isFile()) {
                // zip file to create
                File zipFile = new File( fileToZip.parentFile, zipFileName )
                // only open up the zip if we know it's a file, 
                // and use withCloseable to handle closing the file
                // automatically for us.
    
                new ZipOutputStream(new FileOutputStream(new File( fileToZip.parentFile, zipFileName))).withCloseable { zipStream
                   zipStream.putNextEntry(new ZipEntry(fileToZip.name))
    
                   // no need to create a byte[] array << operator 
                   // will handle copying it (without reading it entirely into memory)
                   fileToZip.withInputStream { stream ->
                       zipStream << stream
                   }
                   zipStream.closeEntry()
                }
                // if we reach here we know we've successfully written the zip
                // file it's safe to clean it up here
                if( cleanUp ) fileToZip.delete()
                return zipFile
            }
            return null
       }
    }