Java Jar文件:使用资源错误: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 。 在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 //.... } 

你不可以做这个

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

这不是一个文件! 当你从IDE运行你没有任何错误,因为你不运行一个jar文件。 在IDE中,类和资源是在文件系统上提取的。

但是你可以这样打开一个InputStream

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

删除"/resource" 。 通常,IDE将文件系统类和资源分开。 但是当这个jar子被创造出来的时候,它们会被放在一起 所以文件夹级别"/resource"仅用于类和资源的分离。

当你从classloader获得资源时,你必须指定资源在jar里面的path,那就是真正的包层次结构。

以下是Eclipse RCP / Plugin开发人员的解决scheme:

 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在临时位置创build一个未打包的版本,以便可以使用File访问该对象。 例如,我猜Lars Vogel在他的文章中有一个错误 – http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/

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

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

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

通过添加以下内容将插件导出为文件夹(而不是jar):

 Eclipse-BundleShape: dir 

到你的MANIFEST.MF

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

除了一般的答案之外,您可以从Unitils库中获得“URI不分层”,试图从.jar文件加载数据集 。 将数据集保存在一个maven子模块中可能会发生,但在另一个子模块中进行实际testing。

甚至有一个UNI-197提交的错误 。