I need to (un)zip some files and after some googling I haven't found any utility for doing it. I know I can do it with built-in java.uitl.zip.* classes but isn't there any utility, that will make it easer, best like this:
SomeClass.unzip("file_name.zip", "target_directory");
or
SomeClass.zip("source_directory", "target_file_name.zip", recursively);
I don't want to handle streams. Just file, or better just file names...
How about the Deflater/Inflater classes mentioned in the question "What’s a good compression library for Java?".
I know the current interfaces proposed by Java are Stream-based, not "filename"-based, but according to the following article on Java compression, it is easy enough to build an utility class around that:
For instance, a Unzip function based on a filename would look like:
import java.io.*;
import java.util.zip.*;
public class UnZip {
final int BUFFER = 2048;
public static void main (String argv[]) {
try {
BufferedOutputStream dest = null;
FileInputStream fis = new
FileInputStream(argv[0]);
ZipInputStream zis = new
ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry;
while((entry = zis.getNextEntry()) != null) {
System.out.println("Extracting: " +entry);
int count;
byte data[] = new byte[BUFFER];
// write the files to the disk
FileOutputStream fos = new
FileOutputStream(entry.getName());
dest = new
BufferedOutputStream(fos, BUFFER);
while ((count = zis.read(data, 0, BUFFER))
!= -1) {
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
zis.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
Maybe Compress from Apache Commons could help you.
jar is a disguised unzipper. Is that usable?
Related
how can I use a determinate progressbar during the unzip process in a Android Application?
I know what I need to file has been processed to update the progressbar, but do not know how to derive this information.
Thank you!
P.S. I use to unzip the code found in this post: https://stackoverflow.com/a/7697493/1364296
how can I use a determinate progressbar during the unzip process in a Android Application?
Use ZipFile to find the number of entries. Use that with setMax() on your ProgressBar to set the upper progress bound. Then, as you process each file, increment the progress by 1.
for the zip code use this .
public static void zip(String[] files, String zipFile) throws IOException {
BufferedInputStream origin = null;
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
try {
byte data[] = new byte[BUFFER_SIZE];
for (int i = 0; i < files.length; i++) {
FileInputStream fi = new FileInputStream(files[i]);
origin = new BufferedInputStream(fi, BUFFER_SIZE);
try {
ZipEntry entry = new ZipEntry(files[i].substring(files[i].lastIndexOf("/") + 1));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER_SIZE)) != -1) {
out.write(data, 0, count);
}
}
finally {
origin.close();
}
}
}
finally {
out.close();
}
}
try to use buffer when zip on unzip because it will be much faster
Is this an efficient way to copy all files with in a directory, including child directories? Is there a chance of infinite recursion? Is there anything I should change? I know it works, but I think there should be an easier way to do this.
private void copy(File file, String path) {
String fileName = file.getPath();
System.out.println(fileName);
fileName = fileName.substring(fileName.lastIndexOf("\\"));
if (path == null)
path = Storage.getStorageDirectoryPath();
File toWrite = new File(path + File.separator + fileName);
if (file.isDirectory()) {
toWrite.mkdir();
File inDirectory[] = file.listFiles();
for (File f : inDirectory)
copy(f, toWrite.getPath());
} else {
try {
InputStream inStream = new FileInputStream(file);
OutputStream outStream = new FileOutputStream(toWrite);
byte buffer[] = new byte[1024];
int length = 0;
while ((length = inStream.read(buffer)) > 0) {
outStream.write(buffer, 0, length);
}
inStream.close();
outStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thanks
Looks pretty good as the comments indicate. You might want to look into the new Java 7 API's (the new NIO). There's a tutorial here, it looks like there are even options to avoid following links.
If you can't use Java 7, old NIO has channels that you can open after opening the file the old way. They include methods transferFrom and transferTo, which might be able to do it more efficiently than you could in Java.
Why reinvent the wheel? take a look at the methods in Apache Common's FileUtils, in particular copyDirectory.
I'm making a modding application for a game. When I unzip and zip the same files: for some reason although it is open-able with 7Zip, it's not open-able in the actual application. Even though I've not edited the unzipped files - it's missing a few bytes.
I gathered the methods from the net and have been editing and retrying for the last 5 hours without success, any help guys? Thanks!
Here's my code:
class zipper
{
static byte[] buffer = new byte[4096];
public static void unzip(File zipfile, File outputfolder) throws Exception
{
JarFile zip = new JarFile(zipfile);
Enumeration entries = zip.entries();
while(entries.hasMoreElements())
{
JarEntry entry = (JarEntry) entries.nextElement();
File unzipped = new File(outputfolder,entry.getName());
if (entry.isDirectory() && !unzipped.exists())
{
unzipped.mkdirs();
continue;
}
else if (!unzipped.getParentFile().exists())
unzipped.getParentFile().mkdirs();
InputStream in = zip.getInputStream(entry);
FileOutputStream fos = new FileOutputStream(unzipped);
int count;
while((count = in.read(buffer, 0, buffer.length)) != -1)
fos.write(buffer, 0, count);
// clean up
fos.close();
in.close();
}
}
public static void zip(File[] infiles, JarOutputStream jos) throws Exception
{
zip(infiles,"",jos);
// clean up
jos.flush();
jos.close();
}
public static void zip(File[] infiles, String basefolder, JarOutputStream jos) throws Exception
{
FileInputStream fis = null;
for(int i=0; i<infiles.length; i++)
{
if(infiles[i].isDirectory())
{
// recursive call for directories
zip(infiles[i].listFiles(), infiles[i].getName() + File.separator, jos);
continue;
}
String filepath = basefolder + infiles[i].getName();
JarEntry entry = new JarEntry(filepath);
jos.putNextEntry(entry);
fis = new FileInputStream(infiles[i]); // get stream
int count;
while((count = fis.read(buffer, 0, buffer.length)) != -1)
jos.write(buffer, 0, count);
}
}
}
Without debugging your code I can say that the most probable reason is the compression level. The default compression level is Deflater.DEFAULT_COMPRESSION. You can change it using ZipOutputStream.setLevel().
I believe that you created your original jar file using jar utility or some other zip creator. Then you created the same using your code and got different size. In this case the compression level may explain the difference.
Actually I am confronted with a Problem. I've got a ".apk-File" in one Package of my Application. apk is a kind of a jar File (apk = Android Package).
I now want to copy this jar-file out of my Programm onto any other Location at the PC.
Normally I would do this by using:
FileInputStream is = new FileInputStream(this.getClass().getResource("/resources/myApp.apk").getFile());
And then write it on the disk with using a FileOutputStream.
... but since an .apk is a kind of a .jar it doesn't work. It just copies the .apk file. but without the containing other files.
any help would be appreciated
Since .apk is a .jar file by another name (in other words it is a zip file with some specific definitions of where configuration files are stored inside the directory) then look at ZipInputStream to read the file and walk through the contents and write them out as files.
Thank you very much Yishai... this was the Hint I was waiting for :)
Probably is sb out there, who needs the to do a same thing, therefore... here is my code:
public static boolean copyApkFile(File outputFile){
try {
FileInputStream fis = new FileInputStream(this.getClass().getResource("/resources/myApkFile.apk").getFile());
ZipInputStream zis = new ZipInputStream(fis);
FileOutputStream fos = new FileOutputStream(outputFile));
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry ze = null;
byte[] buf = new byte[1024];
while ((ze = zis.getNextEntry()) != null) {
System.out.println("Next entry "+ze.getName()+" "+ze.getSize());
zos.putNextEntry(ze);
int len;
while ((len = zis.read(buf)) > 0) {
zos.write(buf, 0, len);
}
}
zos.close();
fos.close();
zis.close();
fis.close();
return true;
} catch (IOException ex) {
Logger.getLogger(SetUpNewDevice.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
}
Basically, I have a jar file that i want to unzip to a specific folder from a junit test.
What is the easiest way to do this?
I am willing to use a free third party library if it's necessary.
You could use java.util.jar.JarFile to iterate over the entries in the file, extracting each one via its InputStream and writing the data out to an external File. Apache Commons IO provides utilities to make this a bit less clumsy.
ZipInputStream in = null;
OutputStream out = null;
try {
// Open the jar file
String inFilename = "infile.jar";
in = new ZipInputStream(new FileInputStream(inFilename));
// Get the first entry
ZipEntry entry = in.getNextEntry();
// Open the output file
String outFilename = "o";
out = new FileOutputStream(outFilename);
// Transfer bytes from the ZIP file to the output file
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
} catch (IOException e) {
// Manage exception
} finally {
// Close the streams
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
}
Jar is basically zipped using ZIP algorithm, so you can use winzip or winrar to extract.
If you are looking for programmatic way then the first answer is more correct.
From command line type jar xf foo.jar or unzip foo.jar
Use the Ant unzip task.
Here's my version in Scala, would be the same in Java, that unpacks into separate files and directories:
import java.io.{BufferedInputStream, BufferedOutputStream, ByteArrayInputStream}
import java.io.{File, FileInputStream, FileOutputStream}
import java.util.jar._
def unpackJar(jar: File, target: File): Seq[File] = {
val b = Seq.newBuilder[File]
val in = new JarInputStream(new BufferedInputStream(new FileInputStream(jar)))
try while ({
val entry: JarEntry = in.getNextJarEntry
(entry != null) && {
val f = new File(target, entry.getName)
if (entry.isDirectory) {
f.mkdirs()
} else {
val bs = new BufferedOutputStream(new FileOutputStream(f))
try {
val arr = new Array[Byte](1024)
while ({
val sz = in.read(arr, 0, 1024)
(sz > 0) && { bs.write(arr, 0, sz); true }
}) ()
} finally {
bs.close()
}
}
b += f
true
}
}) () finally {
in.close()
}
b.result()
}