Someone told me it would be great if ths code could be applied to an array of files.
That's a good use case, isn't it ? So, I thought about it and saw immediately which groovy 'magic item' could be useful : the spread operator aka star-dot operator, mister *.
Better than I could explain myself, here's what's said about this little thing in Groovy's doc :
The Spread Operator is used to invoke an action on all items of an aggregate object.
Unfortunately, ZipOutputStream in Java doesn't permit to append something to a zip file. So, I'll show you an awful (yes, unzip the existing zip-append file-rezip IS awful) implementation of this functionnality. It's just for fun, not for production, after all.
First, you'll need a deleteDir closure, as java.io.File.delete() doesn't delete non-empty directories :
def deleteDir deleteDir = { File f -> if (f?.exists()){ f.listFiles().each{ sf -> sf.isDirectory()?deleteDir(sf):sf.delete() } } f?.delete() }
With this wonderful snippet, you can replace the File.metaClass.zip block in this snippet by :
File.metaClass.zip = { String destination -> //cache the delegate (the File Object) as it will be modified //in the withStream closure def input = delegate if (destination == null){ destination = input.canonicalPath + ".zip" } def dest = new File(destination) def append = false def tmp if (dest.exists()){ tmp = new File(System.properties['java.io.tmpdir'] + File.separator + 'grooz') tmp.mkdir() dest.unzip(tmp.canonicalPath) append = true } def result = new ZipOutputStream(new FileOutputStream(destination)) try{ result.withStream {zipOutStream-> //recursively zip files if (append) { tmp.eachFile{ zip(zipOutStream,it,"") } } zip(zipOutStream,input,"") } } catch(all){ all.printStackTrace() } finally{ deleteDir(tmp) } }
This version is very easy to use. If you want to zip a bunch of files, then list them and use the spread operator like this :
// to zip all files in a directory new File('/path/to/dir').listFiles()*.zip('allmyfiles.zip') //if you've got files instances [file1,file2,dir1,dir2]*.zip('stuff.zip')
This code is not performance-friendly nor beauty-frienly and is provided as is. Every enhancement you can think of is welcome (yes, I know, it'll be difficult to improve, but you can do it ;-) )
See you soon with a totally new subject : joy of Java Classoading !
Pretty slick.
ReplyDelete