2013-07-04 1 views
5

. Метод 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 теста случаев. Во-первых, исполняемый банк запускается из каталога «D: \ test123! @ #» Без проблем. Во-вторых, исполняемый банк запускается из каталога «D: \ test123! @ # !!!», с проблемами.

Не указаны ли каталоги, заканчивающиеся восклицательным знаком? Код неправильный?

Заранее спасибо.

Error when running the executable jar in a directory ending with !

+0

Есть ли причина, вы можете создавать/использовать каталоги с обычными именами? – mtk

+0

Вы уверены, что вы поставили равные банки в оба каталога? – Andremoniy

+0

Пользователи могут выполнять мое приложение из любого места в своей файловой системе. Каталоги с восклицательными знаками поддерживаются Windows. – Velth

ответ

7

Вероятно, из-за этой ошибки или любой из множества подобных ошибок в базе данных ошибок Java: «! /»

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

Причина в том, что в баночке URL интерпретируется как разделитель между именем файла JAR и контуром в самом JAR. Если имя каталога заканчивается на!, Последовательность символов «! /» В конце каталога неверно интерпретируется. В вашем случае, вы на самом деле пытаетесь получить доступ к ресурсу с помощью следующего URL:

баночки: Файл: /// D:/test1231 @ # !!! /test.jar /images/Logo.png

Ошибка была открыта почти 12 лет и вряд ли будет исправлена. На самом деле я не знаю, как это можно исправить, не нарушая других вещей. Проблема заключается в конструктивном решении использовать! как персонаж с особым значением (разделитель) в схеме URL для JAR-файлов:

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

Поскольку восклицательный знак является разрешенным символ в URL, это может произойти как в URL для самого JAR-файла, как и так же как на пути в файле JAR, что делает невозможным в некоторых случаях найти фактический разделитель «! /».

+0

Я понял, что ему нужно что-то делать с Java и анализировать URL-адреса с помощью «! /», Но я просто не мог поверить, что это будет ошибкой. Во всяком случае, может ли быть обходной путь для решения этой проблемы? – Velth

+0

Нет, как также отмечено в ошибке, с которой я связан, нет тривиального обходного пути для этой проблемы. – jarnbjo

1

Простая работа для Windows заключается в использовании «\» вместо «/» в пути. Это означало бы, что последовательность символов «! /» Будет найдена после полного пути. Например:

new URL("jar:file:\\d:\\[email protected]#!!!\\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 «/!») До тех пор, разделители не будут исчерпаны, а затем бросить исключение. Поэтому он увидит, что «d: \ test1231 @ # !!» бросает java.io.FileNotFoundException и затем пытается «d: \ test1231 @ # !!! \ test.jar», который существует. Таким образом, не имеет значения, есть ли «!» в пути к файлу или в файлах jar.

В качестве альтернативы «! /» Можно переключить на другое, что является незаконным именем файла или чем-то конкретным (например, «jarpath:»).

Альтернативно, чтобы путь к файлу jar использовал другой параметр.

Примечание:

Это может быть возможным, чтобы переопределить что-то, поменять обработчик, или изменить код, чтобы открыть файл первого затем заглянуть внутрь файла банку позже, но я не смотрел.