I have created a JAR file. Now, I created another Java program. I want to unpack that JAR file in some other directory, meaning I want to do something like unzip.
我创建了一个JAR文件。现在,我创建了另一个Java程序。我想在其他目录中解压缩那个JAR文件,这意味着我想做一些像解压缩这样的事情。
If I run jar -xf filename.jar
this causes some error:
如果我运行jar -xf filename.jar,这会导致一些错误:
Exception in thread "main" java.io.IOException: Cannot run program "jar":
java.io.IOException: error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)
at java.lang.Runtime.exec(Runtime.java:593)`
8 个解决方案
#1
57
Adapt this example: How to extract Java resources from JAR and zip archive
调整此示例:如何从JAR和zip存档中提取Java资源
Or try this code:
或者试试这段代码:
Extract the Contents of ZIP/JAR Files Programmatically
Suppose
jarFile
is the jar/zip file to be extracted.destDir
is the path where it will be extracted:假设jarFile是要提取的jar / zip文件。 destDir是它将被提取的路径:
java.util.jar.JarFile jar = new java.util.jar.JarFile(jarFile); java.util.Enumeration enumEntries = jar.entries(); while (enumEntries.hasMoreElements()) { java.util.jar.JarEntry file = (java.util.jar.JarEntry) enumEntries.nextElement(); java.io.File f = new java.io.File(destDir + java.io.File.separator + file.getName()); if (file.isDirectory()) { // if its a directory, create it f.mkdir(); continue; } java.io.InputStream is = jar.getInputStream(file); // get the input stream java.io.FileOutputStream fos = new java.io.FileOutputStream(f); while (is.available() > 0) { // write contents of 'is' to 'fos' fos.write(is.read()); } fos.close(); is.close(); } jar.close();
#2
7
You can use this code snippet as a reference to get your task done.Its almost the same as the code snippet shown above by @JuanZe except that for those who were getting the FileNotFoundException, i have added a small code snippet that will check if the file does exist and if it doesn't then it will create the parent folder along with the files and will extract the contents of jar file inside the specified destination folder.
您可以使用此代码段作为参考,让您的任务done.Its几乎相同,只是对于那些谁获得通过FileNotFoundException异常上面@JuanZe所示的代码片段,我已经添加了一小段代码,将检查文件确实存在,如果没有,那么它将与文件一起创建父文件夹,并将提取指定目标文件夹内的jar文件的内容。
Code snippet:
public class JarDemo {
public static void main(String[] args) throws java.io.IOException {
java.util.jar.JarFile jarfile = new java.util.jar.JarFile(new java.io.File("E:/sqljdbc4.jar")); //jar file path(here sqljdbc4.jar)
java.util.Enumeration<java.util.jar.JarEntry> enu= jarfile.entries();
while(enu.hasMoreElements())
{
String destdir = "E:/abc/"; //abc is my destination directory
java.util.jar.JarEntry je = enu.nextElement();
System.out.println(je.getName());
java.io.File fl = new java.io.File(destdir, je.getName());
if(!fl.exists())
{
fl.getParentFile().mkdirs();
fl = new java.io.File(destdir, je.getName());
}
if(je.isDirectory())
{
continue;
}
java.io.InputStream is = jarfile.getInputStream(je);
java.io.FileOutputStream fo = new java.io.FileOutputStream(fl);
while(is.available()>0)
{
fo.write(is.read());
}
fo.close();
is.close();
}
}
}
#3
5
JarFile class.
JarFile file = new JarFile("file.jar");
for (Enumeration<JarEntry> enum = file.entries(); enum.hasMoreElements();) {
JarEntry entry = enum.next();
System.out.println(entry.getName());
}
#4
3
Here is what I would do to extract my whole "resources" folder from my jar. It is way more faster to use BufferedReader and BufferedWriter.
这是我要从我的jar中提取整个“resources”文件夹的方法。使用BufferedReader和BufferedWriter的速度更快。
public static boolean extractResourcesToTempFolder() {
try {
//If folder exist, delete it.
String destPath = getTempDir() + File.separator + "JToolkit" + File.separator;
deleteDirectoryRecursive(new File(destPath));
JarFile jarFile = new JarFile(JToolkit.class.getProtectionDomain().getCodeSource().getLocation().getPath());
Enumeration<JarEntry> enums = jarFile.entries();
while (enums.hasMoreElements()) {
JarEntry entry = enums.nextElement();
if (entry.getName().startsWith("resources")) {
File toWrite = new File(destPath + entry.getName());
if (entry.isDirectory()) {
toWrite.mkdirs();
continue;
}
InputStream in = new BufferedInputStream(jarFile.getInputStream(entry));
OutputStream out = new BufferedOutputStream(new FileOutputStream(toWrite));
byte[] buffer = new byte[2048];
for (;;) {
int nBytes = in.read(buffer);
if (nBytes <= 0) {
break;
}
out.write(buffer, 0, nBytes);
}
out.flush();
out.close();
in.close();
}
System.out.println(entry.getName());
}
} catch (IOException ex) {
Logger.getLogger(Methods.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
return true;
}
#5
2
Old question.
Here is a updated answer using :
老问题。这是一个更新的答案使用:
- Java 7
java.nio
to create and copy efficiently entries - Java 8
stream
to sort and collect the entries lexicographically (in order to always create folders first).
Java 7 java.nio可以高效地创建和复制条目
Java 8流以按字典顺序排序和收集条目(以便始终首先创建文件夹)。
Note that I used java.util.zip.ZipFile
(the base class) instead of java.util.jar.JarFile
(the subclass).
The last one performs more things that are not required to "just" extract files from an archive.
So it reduces the overhead and prevents exception rising related to security concerns. But if required you can of course replace ZipFile/ZipEntry
by JarFile/JarEntry
.
请注意,我使用了java.util.zip.ZipFile(基类)而不是java.util.jar.JarFile(子类)。最后一个执行更多不需要“仅”从存档中提取文件的内容。因此,它可以减少开销并防止与安全问题相关的异常上升。但是如果需要,你当然可以用JarFile / JarEntry替换ZipFile / ZipEntry。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class FileUtils {
public static void extractArchive(Path archiveFile, Path destPath) throws IOException {
Files.createDirectories(destPath); // create dest path folder(s)
try (ZipFile archive = new ZipFile(archiveFile.toFile())) {
// sort entries by name to always create folders first
List<? extends ZipEntry> entries = archive.stream()
.sorted(Comparator.comparing(ZipEntry::getName))
.collect(Collectors.toList());
// copy each entry in the dest path
for (ZipEntry entry : entries) {
Path entryDest = destPath.resolve(entry.getName());
if (entry.isDirectory()) {
Files.createDirectory(entryDest);
continue;
}
Files.copy(archive.getInputStream(entry), entryDest);
}
}
}
}
#6
1
Your title doesn't seem to match the question very well but if you really do want to "write [a] java program extracting a jar file" you just need Class JarFile.
你的标题似乎与这个问题不太匹配,但如果你真的想“编写[a] java程序提取jar文件”,你只需要Class JarFile。
#7
1
You can use this very simple library to pack/unpack jar file
您可以使用这个非常简单的库来打包/解压缩jar文件
Very simple
import java.io.File;
import java.util.List;
import fr.stevecohen.jarmanager.JarUnpacker;
class Test {
JarUnpacker jarUnpacker = new JarUnpacker();
File myfile = new File("./myfile.jar");
File unpackDir = new File("./mydir");
List<File> unpacked_files = jarUnpacker.unpack(myfile.getAbsolutePath(), unpackDir.getAbsolutePath());
}
You can also use maven dependency
您还可以使用maven依赖项
<dependency>
<groupId>fr.stevecohen.jarmanager</groupId>
<artifactId>JarManager</artifactId>
<version>0.5.0</version>
</dependency>
You also need my repository
您还需要我的存储库
<repository>
<id>repo-reapersoon</id>
<name>ReaperSoon's repo</name>
<url>http://repo-maven.stevecohen.fr</url>
</repository>
Check the last version with the link bellow to use the last dependency
使用下面的链接检查最后一个版本以使用最后一个依赖项
Please use my public issue tracker if you find some bugs
如果您发现一些错误,请使用我的公共问题跟踪器
#8
0
Well here's my version, using try-with-resources
:
那么这是我的版本,使用try-with-resources:
try (JarFile jarFile = new JarFile(artifact.getFile())) {
for (JarEntry entry : Collections.list(jarFile.entries())) {
try (InputStream is = jarFile.getInputStream(entry)) {
File file = new File(targetDir, entry.getName());
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(is.read());
}
}
}
} catch (IOException e) {
throw new MyException(String.format(
"Unable to open jar %s", artifact.getArtifactId()), e);
}
#1
57
Adapt this example: How to extract Java resources from JAR and zip archive
调整此示例:如何从JAR和zip存档中提取Java资源
Or try this code:
或者试试这段代码:
Extract the Contents of ZIP/JAR Files Programmatically
Suppose
jarFile
is the jar/zip file to be extracted.destDir
is the path where it will be extracted:假设jarFile是要提取的jar / zip文件。 destDir是它将被提取的路径:
java.util.jar.JarFile jar = new java.util.jar.JarFile(jarFile); java.util.Enumeration enumEntries = jar.entries(); while (enumEntries.hasMoreElements()) { java.util.jar.JarEntry file = (java.util.jar.JarEntry) enumEntries.nextElement(); java.io.File f = new java.io.File(destDir + java.io.File.separator + file.getName()); if (file.isDirectory()) { // if its a directory, create it f.mkdir(); continue; } java.io.InputStream is = jar.getInputStream(file); // get the input stream java.io.FileOutputStream fos = new java.io.FileOutputStream(f); while (is.available() > 0) { // write contents of 'is' to 'fos' fos.write(is.read()); } fos.close(); is.close(); } jar.close();
#2
7
You can use this code snippet as a reference to get your task done.Its almost the same as the code snippet shown above by @JuanZe except that for those who were getting the FileNotFoundException, i have added a small code snippet that will check if the file does exist and if it doesn't then it will create the parent folder along with the files and will extract the contents of jar file inside the specified destination folder.
您可以使用此代码段作为参考,让您的任务done.Its几乎相同,只是对于那些谁获得通过FileNotFoundException异常上面@JuanZe所示的代码片段,我已经添加了一小段代码,将检查文件确实存在,如果没有,那么它将与文件一起创建父文件夹,并将提取指定目标文件夹内的jar文件的内容。
Code snippet:
public class JarDemo {
public static void main(String[] args) throws java.io.IOException {
java.util.jar.JarFile jarfile = new java.util.jar.JarFile(new java.io.File("E:/sqljdbc4.jar")); //jar file path(here sqljdbc4.jar)
java.util.Enumeration<java.util.jar.JarEntry> enu= jarfile.entries();
while(enu.hasMoreElements())
{
String destdir = "E:/abc/"; //abc is my destination directory
java.util.jar.JarEntry je = enu.nextElement();
System.out.println(je.getName());
java.io.File fl = new java.io.File(destdir, je.getName());
if(!fl.exists())
{
fl.getParentFile().mkdirs();
fl = new java.io.File(destdir, je.getName());
}
if(je.isDirectory())
{
continue;
}
java.io.InputStream is = jarfile.getInputStream(je);
java.io.FileOutputStream fo = new java.io.FileOutputStream(fl);
while(is.available()>0)
{
fo.write(is.read());
}
fo.close();
is.close();
}
}
}
#3
5
JarFile class.
JarFile file = new JarFile("file.jar");
for (Enumeration<JarEntry> enum = file.entries(); enum.hasMoreElements();) {
JarEntry entry = enum.next();
System.out.println(entry.getName());
}
#4
3
Here is what I would do to extract my whole "resources" folder from my jar. It is way more faster to use BufferedReader and BufferedWriter.
这是我要从我的jar中提取整个“resources”文件夹的方法。使用BufferedReader和BufferedWriter的速度更快。
public static boolean extractResourcesToTempFolder() {
try {
//If folder exist, delete it.
String destPath = getTempDir() + File.separator + "JToolkit" + File.separator;
deleteDirectoryRecursive(new File(destPath));
JarFile jarFile = new JarFile(JToolkit.class.getProtectionDomain().getCodeSource().getLocation().getPath());
Enumeration<JarEntry> enums = jarFile.entries();
while (enums.hasMoreElements()) {
JarEntry entry = enums.nextElement();
if (entry.getName().startsWith("resources")) {
File toWrite = new File(destPath + entry.getName());
if (entry.isDirectory()) {
toWrite.mkdirs();
continue;
}
InputStream in = new BufferedInputStream(jarFile.getInputStream(entry));
OutputStream out = new BufferedOutputStream(new FileOutputStream(toWrite));
byte[] buffer = new byte[2048];
for (;;) {
int nBytes = in.read(buffer);
if (nBytes <= 0) {
break;
}
out.write(buffer, 0, nBytes);
}
out.flush();
out.close();
in.close();
}
System.out.println(entry.getName());
}
} catch (IOException ex) {
Logger.getLogger(Methods.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
return true;
}
#5
2
Old question.
Here is a updated answer using :
老问题。这是一个更新的答案使用:
- Java 7
java.nio
to create and copy efficiently entries - Java 8
stream
to sort and collect the entries lexicographically (in order to always create folders first).
Java 7 java.nio可以高效地创建和复制条目
Java 8流以按字典顺序排序和收集条目(以便始终首先创建文件夹)。
Note that I used java.util.zip.ZipFile
(the base class) instead of java.util.jar.JarFile
(the subclass).
The last one performs more things that are not required to "just" extract files from an archive.
So it reduces the overhead and prevents exception rising related to security concerns. But if required you can of course replace ZipFile/ZipEntry
by JarFile/JarEntry
.
请注意,我使用了java.util.zip.ZipFile(基类)而不是java.util.jar.JarFile(子类)。最后一个执行更多不需要“仅”从存档中提取文件的内容。因此,它可以减少开销并防止与安全问题相关的异常上升。但是如果需要,你当然可以用JarFile / JarEntry替换ZipFile / ZipEntry。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class FileUtils {
public static void extractArchive(Path archiveFile, Path destPath) throws IOException {
Files.createDirectories(destPath); // create dest path folder(s)
try (ZipFile archive = new ZipFile(archiveFile.toFile())) {
// sort entries by name to always create folders first
List<? extends ZipEntry> entries = archive.stream()
.sorted(Comparator.comparing(ZipEntry::getName))
.collect(Collectors.toList());
// copy each entry in the dest path
for (ZipEntry entry : entries) {
Path entryDest = destPath.resolve(entry.getName());
if (entry.isDirectory()) {
Files.createDirectory(entryDest);
continue;
}
Files.copy(archive.getInputStream(entry), entryDest);
}
}
}
}
#6
1
Your title doesn't seem to match the question very well but if you really do want to "write [a] java program extracting a jar file" you just need Class JarFile.
你的标题似乎与这个问题不太匹配,但如果你真的想“编写[a] java程序提取jar文件”,你只需要Class JarFile。
#7
1
You can use this very simple library to pack/unpack jar file
您可以使用这个非常简单的库来打包/解压缩jar文件
Very simple
import java.io.File;
import java.util.List;
import fr.stevecohen.jarmanager.JarUnpacker;
class Test {
JarUnpacker jarUnpacker = new JarUnpacker();
File myfile = new File("./myfile.jar");
File unpackDir = new File("./mydir");
List<File> unpacked_files = jarUnpacker.unpack(myfile.getAbsolutePath(), unpackDir.getAbsolutePath());
}
You can also use maven dependency
您还可以使用maven依赖项
<dependency>
<groupId>fr.stevecohen.jarmanager</groupId>
<artifactId>JarManager</artifactId>
<version>0.5.0</version>
</dependency>
You also need my repository
您还需要我的存储库
<repository>
<id>repo-reapersoon</id>
<name>ReaperSoon's repo</name>
<url>http://repo-maven.stevecohen.fr</url>
</repository>
Check the last version with the link bellow to use the last dependency
使用下面的链接检查最后一个版本以使用最后一个依赖项
Please use my public issue tracker if you find some bugs
如果您发现一些错误,请使用我的公共问题跟踪器
#8
0
Well here's my version, using try-with-resources
:
那么这是我的版本,使用try-with-resources:
try (JarFile jarFile = new JarFile(artifact.getFile())) {
for (JarEntry entry : Collections.list(jarFile.entries())) {
try (InputStream is = jarFile.getInputStream(entry)) {
File file = new File(targetDir, entry.getName());
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(is.read());
}
}
}
} catch (IOException e) {
throw new MyException(String.format(
"Unable to open jar %s", artifact.getArtifactId()), e);
}