无法在以感叹号结尾的目录中打开资源(!)

每当在以感叹号结尾的目录中运行可执行jar时, getResourceAsStream -method都返回null。

对于以下示例,我有一个Eclipse项目具有以下目录结构:

src\ (Source Folder) main\ (Package) Main.java res\ (Source Folder) images\ Logo.png 

我正在阅读Logo.png如下:

 public static void main(String[] args) throws IOException { try (InputStream is = Main.class.getClassLoader().getResourceAsStream("images/Logo.png")) { Image image = ImageIO.read(is); System.out.println(image); } } 

请参阅2个测试用例的附件。 首先,可执行jar从目录“D:\ test123!@#”启动而没有任何问题。 其次,可执行jar从目录“D:\ test123!@#!!!”启动,有问题。

是否不支持以感叹号结尾的目录? 代码错了吗?

提前致谢。

在以!结尾的目录中运行可执行jar时出错!

可能是因为这个bug或Java bug数据库中的许多类似错误:

http://sofzh.miximages.com/java/view_bug.do

该漏洞已经开放了近12年,不太可能被修复。 实际上我不知道如何在不破坏其他事情的情况下修复它。 问题是设计决定使用! 作为JAR文件的URL方案中具有特殊含义(分隔符)的字符:

 jar:!/ 

由于感叹号是URL中允许的字符,因此它可能出现在JAR文件本身的URL中,也可能出现在JAR文件中的路径中,这使得在某些情况下无法找到实际的“!/”分隔符。

对Windows的一个简单解决方法是在路径中使用“\”而不是“/”。 这意味着在完整路径之后找到“!/”字符序列。 例如:

 new URL("jar:file:\\d:\\test1231@#!!!\\test.jar!/images/Logo.png"); 

我的代码:

 File jar = new File(jarPath + "/" + jarName); URL url = new URL("jar:" + jar.toURI() + "!" + dataFilePath); InputStream stream = null; try { stream = url.openStream(); } catch (FileNotFoundException e) { // Windows fix URL urlFix = new URL("jar:" + jar.toURI().toString().replace('/', '\\') + "!" + dataFilePath); stream = urlFix.openStream(); } 

我使用toURI()因为它处理像空格这样的东西。

修正:

修复本身将由Java检查文件是否存在,如果没有继续到下一个分隔符(url的“!/”部分),直到分隔符耗尽,然后抛出exception。 所以它会看到“d:\ test1231 @#!!” 抛出java.io.FileNotFoundException然后尝试“d:\ test1231 @#!!! \ test.jar”确实存在。 这样,如果有“!”就没关系 在文件路径或jar的文件中。

或者,“!/”可以切换到其他非法文件名或特定内容(如“jarpath:”)。

或者,使jar的文件路径使用另一个参数。

注意:

有可能覆盖某些东西,交换处理程序,或者更改代码以先打开文件,然后再查看jar文件,但我没看过。