Unable to open resources in directories which end with an exclamation mark (!)

戏子无情 提交于 2019-11-28 11:26:48

Probably because of this bug or any of the many similar bugs in the Java bug database:

http://bugs.sun.com/view_bug.do?bug_id=4523159

The reason is that "!/" in a jar URL is interpreted as the separator between the JAR file name and the path within the JAR itself. If a directory name ends with !, the "!/" character sequence at the end of the directory is incorrectly interpreted. In your case, you are actually trying to access a resource with the following URL:

jar:file:///d:/test1231@#!!!/test.jar!/images/Logo.png

The bug has been open for almost 12 years and is not likely to be fixed. Actually I don't know how it can be fixed without breaking other things. The problem is the design decision to use ! as a character with a special meaning (separator) in the URL scheme for JAR files:

jar:<URL for JAR file>!/<path within the JAR file>

Since the exclamation mark is an allowed character in URLs, it may occur both in the URL to the JAR file itself, as well as in the path within the JAR file, making it impossible in some cases to find the actual "!/" separator.

A simple work around for Windows is to use "\" instead of "/" in the path. That would mean the "!/" character sequence is found after the full path. For instance:

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

My Code:

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();
}

I use toURI() because it handles things like spaces.

Fixes:

The fix itself would be for Java to check if the file exists and if not continue to the next separator (the "!/" part of the url) until the separators are exhausted, then throw the exception. So it would see that "d:\test1231@#!!" throws a java.io.FileNotFoundException and would then try "d:\test1231@#!!!\test.jar" which does exist. This way it does not matter if there are "!" in the file path or in the jar's files.

Alternatively the "!/" can be switched to something else that is an illegal file name or to something specific (like "jarpath:").

Alternatively make the jar's file path use another parameter.

Note:

It may be possible to override something, swap a handler, or change the code to open the file first then look inside the jar file later but I have not looked.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!