Мне нужно было сделать это, потому что API, который я использовал, требовал параметра File, который нельзя получить из ресурса в JAR.
Я обнаружил, что ответ @Emre работает неправильно. По какой-то причине ZipEntry пропустил несколько файлов в JAR (никакой очевидной картины для этого). Я исправил это, используя вместо этого JarEntry. В приведенном выше коде также есть ошибка, из-за которой файл в zip-записи может быть перечислен до появления каталога, что вызывает исключение, поскольку каталог еще не создан.
Обратите внимание, что приведенный ниже код зависит от служебных классов 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;
}