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