JavaJar 文件: 使用资源错误: URI 不是分层的

我已经将我的应用程序部署到 jar 文件。当我需要将数据从一个资源文件复制到 jar 文件之外时,我会执行以下代码:

URL resourceUrl = getClass().getResource("/resource/data.sav");
File src = new File(resourceUrl.toURI()); //ERROR HERE
File dst = new File(CurrentPath()+"data.sav");  //CurrentPath: path of jar file don't include jar file name
FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst);
// some excute code here

我遇到的错误是: URI is not hierarchical.this 在 IDE 中运行时不会遇到的错误。

如果我在 StackOverFlow 的其他文章中修改了上面的代码,作为一些帮助:

InputStream in = Model.class.getClassLoader().getResourceAsStream("/resource/data.sav");
File dst = new File(CurrentPath() + "data.sav");
FileOutputStream out = new FileOutputStream(dst);
//....
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) { //NULL POINTER EXCEPTION
//....
}
103481 次浏览

你不能这么做

File src = new File(resourceUrl.toURI()); //ERROR HERE

这不是文件! 从 ide 运行时不会出现任何错误,因为不运行 jar 文件。在 IDE 中的类和资源是在文件系统上提取的。

但是你可以这样打开 InputStream:

InputStream in = Model.class.getClassLoader().getResourceAsStream("/data.sav");

移除 "/resource"。通常,IDE 在文件系统类和资源上是分开的。但是当这个罐子被创造出来的时候,它们被放在了一起。因此,文件夹级别 "/resource"仅用于类和资源分离。

从类加载器获取资源时,必须指定资源在 jar 中的路径,即真正的包层次结构。

当我偶然发现这个问题时,我想添加另一个选项(来自@dash1e 的完美解释) :

将插件导出为一个文件夹(而不是一个 jar) ,方法是添加:

Eclipse-BundleShape: dir

到你的 MANIFEST.MF

至少当您使用导出向导(基于 *.product)文件导出您的 RCP 应用程序时,这将得到尊重并产生一个文件夹。

下面是 Eclipse RCP/Plugin 开发人员的解决方案:

Bundle bundle = Platform.getBundle("resource_from_some_plugin");
URL fileURL = bundle.getEntry("files/test.txt");
File file = null;
try {
URL resolvedFileURL = FileLocator.toFileURL(fileURL);


// We need to use the 3-arg constructor of URI in order to properly escape file system chars
URI resolvedURI = new URI(resolvedFileURL.getProtocol(), resolvedFileURL.getPath(), null);
File file = new File(resolvedURI);
} catch (URISyntaxException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}

使用 FileLocator.toFileURL(fileURL)而不是 resolve(fileURL)非常重要 ,因为当插件被打包到一个 jar 中时,这将导致 Eclipse 在一个临时位置创建一个未打包的版本,以便可以使用 File 访问该对象。例如,我猜测拉尔斯 · 沃格尔在他的文章中有一个错误—— http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/

如果出于某种原因,您确实需要创建一个 java.io.File对象来指向 Jar 文件中的资源,那么答案就在这里: https://stackoverflow.com/a/27149287/155167

File f = new File(getClass().getResource("/MyResource").toExternalForm());

除了一般的答案之外,您还可以从试图从 .jar文件加载 数据集直到库中获得“ URI 不是分层的”。这可能发生在将数据集保存在一个 maven 子模块中,而将实际测试保存在另一个子模块中时。

甚至还有一份 UNI-197号窃听器文件。

我以前也遇到过类似的问题,我使用了代码:

new File(new URI(url.toString().replace(" ","%20")).getSchemeSpecificPart());

而不是密码:

new File(new URI(url.toURI())

来解决这个问题