java 我应该如何在java中提取压缩文件夹?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/938958/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How should I extract compressed folders in java?
提问by Chathuranga Chandrasekara
I am using the following code to extract a zip file in Java.
我正在使用以下代码在 Java 中提取 zip 文件。
import java.io.*;
import java.util.zip.*;
class testZipFiles
{
public static void main(String[] args)
{
try
{
String filename = "C:\zip\includes.zip";
testZipFiles list = new testZipFiles( );
list.getZipFiles(filename);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void getZipFiles(String filename)
{
try
{
String destinationname = "c:\zip\";
byte[] buf = new byte[1024];
ZipInputStream zipinputstream = null;
ZipEntry zipentry;
zipinputstream = new ZipInputStream(
new FileInputStream(filename));
zipentry = zipinputstream.getNextEntry();
while (zipentry != null)
{
//for each entry to be extracted
String entryName = zipentry.getName();
System.out.println("entryname "+entryName);
int n;
FileOutputStream fileoutputstream;
File newFile = new File(entryName);
String directory = newFile.getParent();
if(directory == null)
{
if(newFile.isDirectory())
break;
}
fileoutputstream = new FileOutputStream(
destinationname+entryName);
while ((n = zipinputstream.read(buf, 0, 1024)) > -1)
fileoutputstream.write(buf, 0, n);
fileoutputstream.close();
zipinputstream.closeEntry();
zipentry = zipinputstream.getNextEntry();
}//while
zipinputstream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Obviously this will not extract a folder tree because of the break statement. I tried to use recursion to process a folder tree but failed. Could someone show me how to improve this code to handle a folder tree instead of a compressed single level folder.
显然,由于 break 语句,这不会提取文件夹树。我尝试使用递归来处理文件夹树,但失败了。有人可以告诉我如何改进此代码以处理文件夹树而不是压缩的单级文件夹。
采纳答案by Emre
You can use File.mkdirs() to create folders. Try changing your method like this:
您可以使用 File.mkdirs() 创建文件夹。尝试像这样改变你的方法:
public static void getZipFiles(String filename) {
try {
String destinationname = "c:\zip\";
byte[] buf = new byte[1024];
ZipInputStream zipinputstream = null;
ZipEntry zipentry;
zipinputstream = new ZipInputStream(
new FileInputStream(filename));
zipentry = zipinputstream.getNextEntry();
while (zipentry != null) {
//for each entry to be extracted
String entryName = destinationname + zipentry.getName();
entryName = entryName.replace('/', File.separatorChar);
entryName = entryName.replace('\', File.separatorChar);
System.out.println("entryname " + entryName);
int n;
FileOutputStream fileoutputstream;
File newFile = new File(entryName);
if (zipentry.isDirectory()) {
if (!newFile.mkdirs()) {
break;
}
zipentry = zipinputstream.getNextEntry();
continue;
}
fileoutputstream = new FileOutputStream(entryName);
while ((n = zipinputstream.read(buf, 0, 1024)) > -1) {
fileoutputstream.write(buf, 0, n);
}
fileoutputstream.close();
zipinputstream.closeEntry();
zipentry = zipinputstream.getNextEntry();
}//while
zipinputstream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
回答by hd1
Another option is commons-compress, for which there is sample code on the site linked above.
另一种选择是commons-compress,上面链接的站点上有示例代码。
回答by bcoughlan
I needed to do this because of an API which I was using required a File parameter, which you can't get from a resource in a JAR.
我需要这样做是因为我使用的 API 需要一个 File 参数,您无法从 JAR 中的资源中获取该参数。
I found that the answer from @Emre didn't work correctly. For some reason ZipEntry skipped a few files in the JAR (no apparent pattern to this). I fixed this by using JarEntry instead. There is also a bug in the above code where the file in the zip entry could be enumerated before the directory is, which causes an exception because the directory hasn't been created yet.
我发现@Emre 的答案没有正常工作。出于某种原因,ZipEntry 跳过了 JAR 中的一些文件(对此没有明显的模式)。我改用 JarEntry 解决了这个问题。上面的代码中还有一个bug,就是zip条目中的文件可能会先于目录被枚举,导致一个异常,因为目录还没有被创建。
Note that the below code depends on Apache Commons utility classes.
请注意,以下代码取决于 Apache Commons 实用程序类。
/**
*
* Extract a directory in a JAR on the classpath to an output folder.
*
* Note: User's responsibility to ensure that the files are actually in a JAR.
* The way that I do this is to get the URI with
* URI url = getClass().getResource("/myresource").toURI();
* and then if url.isOpaque() we are in a JAR. There may be a more reliable
* way however, please edit this answer if you know of one.
*
* @param classInJar A class in the JAR file which is on the classpath
* @param resourceDirectory Path to resource directory in JAR
* @param outputDirectory Directory to write to
* @return String containing the path to the folder in the outputDirectory
* @throws IOException
*/
private static String extractDirectoryFromClasspathJAR(Class<?> classInJar, String resourceDirectory, String outputDirectory)
throws IOException {
resourceDirectory = StringUtils.strip(resourceDirectory, "\/") + File.separator;
URL jar = classInJar.getProtectionDomain().getCodeSource().getLocation();
//Note: If you want to extract from a named JAR, remove the above
//line and replace "jar.getFile()" below with the path to the JAR.
JarFile jarFile = new JarFile(new File(jar.getFile()));
byte[] buf = new byte[1024];
Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
if (jarEntry.isDirectory() || !jarEntry.getName().startsWith(resourceDirectory)) {
continue;
}
String outputFileName = FilenameUtils.concat(outputDirectory, jarEntry.getName());
//Create directories if they don't exist
new File(FilenameUtils.getFullPath(outputFileName)).mkdirs();
//Write file
FileOutputStream fileOutputStream = new FileOutputStream(outputFileName);
int n;
InputStream is = jarFile.getInputStream(jarEntry);
while ((n = is.read(buf, 0, 1024)) > -1) {
fileOutputStream.write(buf, 0, n);
}
is.close();
fileOutputStream.close();
}
jarFile.close();
String fullPath = FilenameUtils.concat(outputDirectory, resourceDirectory);
return fullPath;
}

