Mac*_*rse 32 java jar getresource
我最近开发了一个应用程序并创建了jar文件.
我的一个类创建了一个输出目录,用它的资源填充文件.
我的代码是这样的:
// Copy files from dir "template" in this class resource to output.
private void createOutput(File output) throws IOException {
File template = new File(FileHelper.URL2Path(getClass().getResource("template")));
FileHelper.copyDirectory(template, output);
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,这不起作用.
没有运气我尝试了以下内容:
使用Streams解决其他类的类似问题,但它不适用于dirs.代码类似于 http://www.exampledepot.com/egs/java.io/CopyFile.html
使用创建文件模板 new File(getClass().getResource("template").toUri())
在写这篇文章的时候,我正在思考而不是在资源路径中有一个模板目录,而是有一个zip文件.这样做我可以将文件作为inputStream并将其解压缩到我需要的位置.但我不确定这是不是正确的方法.
小智 16
谢谢你的解决方案!对于其他人,以下内容不使用辅助类(StringUtils除外)
/ 我为此解决方案添加了额外的信息,检查代码的结尾,Zegor V /
public class FileUtils {
public static boolean copyFile(final File toCopy, final File destFile) {
try {
return FileUtils.copyStream(new FileInputStream(toCopy),
new FileOutputStream(destFile));
} catch (final FileNotFoundException e) {
e.printStackTrace();
}
return false;
}
private static boolean copyFilesRecusively(final File toCopy,
final File destDir) {
assert destDir.isDirectory();
if (!toCopy.isDirectory()) {
return FileUtils.copyFile(toCopy, new File(destDir, toCopy.getName()));
} else {
final File newDestDir = new File(destDir, toCopy.getName());
if (!newDestDir.exists() && !newDestDir.mkdir()) {
return false;
}
for (final File child : toCopy.listFiles()) {
if (!FileUtils.copyFilesRecusively(child, newDestDir)) {
return false;
}
}
}
return true;
}
public static boolean copyJarResourcesRecursively(final File destDir,
final JarURLConnection jarConnection) throws IOException {
final JarFile jarFile = jarConnection.getJarFile();
for (final Enumeration<JarEntry> e = jarFile.entries(); e.hasMoreElements();) {
final JarEntry entry = e.nextElement();
if (entry.getName().startsWith(jarConnection.getEntryName())) {
final String filename = StringUtils.removeStart(entry.getName(), //
jarConnection.getEntryName());
final File f = new File(destDir, filename);
if (!entry.isDirectory()) {
final InputStream entryInputStream = jarFile.getInputStream(entry);
if(!FileUtils.copyStream(entryInputStream, f)){
return false;
}
entryInputStream.close();
} else {
if (!FileUtils.ensureDirectoryExists(f)) {
throw new IOException("Could not create directory: "
+ f.getAbsolutePath());
}
}
}
}
return true;
}
public static boolean copyResourcesRecursively( //
final URL originUrl, final File destination) {
try {
final URLConnection urlConnection = originUrl.openConnection();
if (urlConnection instanceof JarURLConnection) {
return FileUtils.copyJarResourcesRecursively(destination,
(JarURLConnection) urlConnection);
} else {
return FileUtils.copyFilesRecusively(new File(originUrl.getPath()),
destination);
}
} catch (final IOException e) {
e.printStackTrace();
}
return false;
}
private static boolean copyStream(final InputStream is, final File f) {
try {
return FileUtils.copyStream(is, new FileOutputStream(f));
} catch (final FileNotFoundException e) {
e.printStackTrace();
}
return false;
}
private static boolean copyStream(final InputStream is, final OutputStream os) {
try {
final byte[] buf = new byte[1024];
int len = 0;
while ((len = is.read(buf)) > 0) {
os.write(buf, 0, len);
}
is.close();
os.close();
return true;
} catch (final IOException e) {
e.printStackTrace();
}
return false;
}
private static boolean ensureDirectoryExists(final File f) {
return f.exists() || f.mkdir();
}
}
Run Code Online (Sandbox Code Playgroud)
它仅使用Apache Software Foundation中的一个外部库,但所使用的功能仅限于:
public static String removeStart(String str, String remove) {
if (isEmpty(str) || isEmpty(remove)) {
return str;
}
if (str.startsWith(remove)){
return str.substring(remove.length());
}
return str;
}
public static boolean isEmpty(CharSequence cs) {
return cs == null || cs.length() == 0;
}
Run Code Online (Sandbox Code Playgroud)
我的知识仅限于Apache许可证,但您可以在没有库的代码中使用此方法.但是,如果有的话,我不对许可证问题负责.
Vin*_*jip 11
我认为你使用zip文件的方法是有道理的.大概你会做一个getResourceAsStream
来获取zip的内部,这在逻辑上看起来像一个目录树.
骨架方法:
InputStream is = getClass().getResourceAsStream("my_embedded_file.zip");
ZipInputStream zis = new ZipInputStream(is);
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
// do something with the entry - for example, extract the data
}
Run Code Online (Sandbox Code Playgroud)
lpi*_*ora 11
使用Java7 +可以通过创建FileSystem
然后使用walkFileTree
递归复制文件来实现.
public void copyFromJar(String source, final Path target) throws URISyntaxException, IOException {
URI resource = getClass().getResource("").toURI();
FileSystem fileSystem = FileSystems.newFileSystem(
resource,
Collections.<String, String>emptyMap()
);
final Path jarPath = fileSystem.getPath(source);
Files.walkFileTree(jarPath, new SimpleFileVisitor<Path>() {
private Path currentTarget;
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
currentTarget = target.resolve(jarPath.relativize(dir).toString());
Files.createDirectories(currentTarget);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.copy(file, target.resolve(jarPath.relativize(file).toString()), StandardCopyOption.REPLACE_EXISTING);
return FileVisitResult.CONTINUE;
}
});
}
Run Code Online (Sandbox Code Playgroud)
该方法可以这样使用:
copyFromJar("/path/to/the/template/in/jar", Paths.get("/tmp/from-jar"))
Run Code Online (Sandbox Code Playgroud)
我讨厌使用之前发布的ZIP文件方法的想法,所以我想出了以下内容.
public void copyResourcesRecursively(URL originUrl, File destination) throws Exception {
URLConnection urlConnection = originUrl.openConnection();
if (urlConnection instanceof JarURLConnection) {
copyJarResourcesRecursively(destination, (JarURLConnection) urlConnection);
} else if (urlConnection instanceof FileURLConnection) {
FileUtils.copyFilesRecursively(new File(originUrl.getPath()), destination);
} else {
throw new Exception("URLConnection[" + urlConnection.getClass().getSimpleName() +
"] is not a recognized/implemented connection type.");
}
}
public void copyJarResourcesRecursively(File destination, JarURLConnection jarConnection ) throws IOException {
JarFile jarFile = jarConnection.getJarFile();
for (JarEntry entry : CollectionUtils.iterable(jarFile.entries())) {
if (entry.getName().startsWith(jarConnection.getEntryName())) {
String fileName = StringUtils.removeStart(entry.getName(), jarConnection.getEntryName());
if (!entry.isDirectory()) {
InputStream entryInputStream = null;
try {
entryInputStream = jarFile.getInputStream(entry);
FileUtils.copyStream(entryInputStream, new File(destination, fileName));
} finally {
FileUtils.safeClose(entryInputStream);
}
} else {
FileUtils.ensureDirectoryExists(new File(destination, fileName));
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
示例用法(将类路径资源"config"中的所有文件复制到"$ {homeDirectory}/config":
File configHome = new File(homeDirectory, "config/");
//noinspection ResultOfMethodCallIgnored
configHome.mkdirs();
copyResourcesRecursively(super.getClass().getResource("/config"), configHome);
Run Code Online (Sandbox Code Playgroud)
这应该适用于从平面文件和Jar文件复制.
注意:上面的代码使用了一些自定义实用程序类(FileUtils,CollectionUtils)以及Apache commons-lang(StringUtils)中的一些代理实用程序类,但是这些函数应该非常明显地命名.
小智 6
lpiepiora 的回答,是正确的!但是有个小问题,源码,应该是jar Url。当源路径是文件系统的路径时,上面的代码将无法正常工作。为了解决这个问题,你应该使用ReferencePath,代码,你可以从以下链接中获取: Read from file system via FileSystem object copyFromJar 的新代码应该是这样的:
public class ResourcesUtils {
public static void copyFromJar(final String sourcePath, final Path target) throws URISyntaxException,
IOException {
final PathReference pathReference = PathReference.getPath(new URI(sourcePath));
final Path jarPath = pathReference.getPath();
Files.walkFileTree(jarPath, new SimpleFileVisitor<Path>() {
private Path currentTarget;
@Override
public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException {
currentTarget = target.resolve(jarPath.relativize(dir)
.toString());
Files.createDirectories(currentTarget);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
Files.copy(file, target.resolve(jarPath.relativize(file)
.toString()), StandardCopyOption.REPLACE_EXISTING);
return FileVisitResult.CONTINUE;
}
});
}
public static void main(final String[] args) throws MalformedURLException, URISyntaxException, IOException {
final String sourcePath = "jar:file:/c:/temp/example.jar!/src/main/resources";
ResourcesUtils.copyFromJar(sourcePath, Paths.get("c:/temp/resources"));
}
Run Code Online (Sandbox Code Playgroud)