问题
given a zip file with multiple nested directory structure, how do I unzip it into the same tree structure? does ZipFile.entries() provide the enumeration in any order?
回答1:
Zip doesn't offer directory structure per se. The tree alike structure is built by having full path of each entry. ZipFile enumerates the entries in the same way they have been added to the file.
Note: java.util.ZipEntry.isDirectory() just tests if the last character of the name is '/', that's how it works.
What you need to extract the files into the same directory. Parse then name like that:
for(ZipEntry zipEntry : java.util.Collections.list(zipFile.entries())){//lazislav
String name = zipEntry.getName();
int idx = name.lastIndexOf('/');
if (idx>=0) name=name.substring(idx)
if (name.length()==0) continue;
File f = new File(targetDir, name);
}
That shall do it more or less (you still need to take care of duplicate file names, etc)
回答2:
This is mine.
In file you specify the file you want to expand in target dir you have to specify the target location as "new File("/tmp/foo/bar")". If you want to extract in the current directory you can specify targetDir = new File(".")
public static void unzip(File file, File targetDir) throws ZipException,
IOException {
targetDir.mkdirs();
ZipFile zipFile = new ZipFile(file);
try {
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
File targetFile = new File(targetDir, entry.getName());
if (entry.isDirectory()) {
targetFile.mkdirs();
} else {
InputStream input = zipFile.getInputStream(entry);
try {
OutputStream output = new FileOutputStream(targetFile);
try {
copy(input, output);
} finally {
output.close();
}
} finally {
input.close();
}
}
}
} finally {
zipFile.close();
}
}
private static void copy(InputStream input, OutputStream output)
throws IOException {
byte[] buffer = new byte[4096];
int size;
while ((size = input.read(buffer)) != -1)
output.write(buffer, 0, size);
}
Worked for me. Good luck.
回答3:
Here's the one I use all the times. It should directly work after a copy/paste and in any circumstances.
public static File unzip(File inFile, File outFolder)
{ final int BUFFER = 2048;
try
{
BufferedOutputStream out = null;
ZipInputStream in = new ZipInputStream(
new BufferedInputStream(
new FileInputStream(inFile)));
ZipEntry entry;
while((entry = in.getNextEntry()) != null)
{
//System.out.println("Extracting: " + entry);
int count;
byte data[] = new byte[BUFFER];
//We will try to reconstruct the entry directories
File entrySupposedPath = new File(outFolder.getAbsolutePath()+File.separator+entry.getName());
//Does the parent folder exist?
if (!entrySupposedPath.getParentFile().exists()){
entrySupposedPath.getParentFile().mkdirs();
}
// write the files to the disk
out = new BufferedOutputStream(
new FileOutputStream(outFolder.getPath() + "/" + entry.getName()),BUFFER);
while ((count = in.read(data,0,BUFFER)) != -1)
{
out.write(data,0,count);
}
out.flush();
out.close();
}
in.close();
return outFolder;
}
catch(Exception e)
{
e.printStackTrace();
return inFile;
}
}
回答4:
ZipFile zipFile = new ZipFile("archive.zip");
try {
for (Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) {
ZipEntry entry = entries.nextElement();
if (entry.isDirectory()) {
new File(entry.getName()).mkdirs();
} else {
InputStream in = zipFile.getInputStream(entry);
try {
OutputStream out = new BufferedOutputStream(new FileOutputStream(entry.getName()));
try {
// this util class is taken from apache commons io (see http://commons.apache.org/io/)
IOUtils.copy(in, out);
} finally {
out.close();
}
} finally {
in.close();
}
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
zipFile.close();
}
回答5:
Why do you care about order?
If the ZipFile entry has a name /a/b/c/file.txt
, then you can work out the directory name /a/b/c
and then create a directory in your tree called a/b/c
.
来源:https://stackoverflow.com/questions/4722049/unzip-a-zipfile-in-the-same-hierachy-using-java-util-zipfile