Java в Ma c OS X Catalina - Zip-файл не найден в ресурсах, в то время как файл обнаруживается при запуске из Eclipse - PullRequest
0 голосов
/ 19 июня 2020

У меня есть сжатый файл в папке «Ресурсы», который распаковывается в папке, в которой программа запускается впервые. Если программа запускается из Eclipse, файл обнаруживается и распаковывается без проблем. Когда я экспортирую программу в файл jar и запускаю программу с:

java -jar JRS2020-31.jar

, результат будет:

java.lang.RuntimeException: Error unzipping file initialData/compressed.zip
    at InterpreteSQL.Main.unzip(Main.java:111)
    at InterpreteSQL.Main.CreateInitialDirectoryIfNotFound(Main.java:77)
    at InterpreteSQL.Main.main(Main.java:60)
Caused by: java.io.FileNotFoundException: file:/Users/XXX/JRS2020-31.jar!/initialData/compressed.zip (No such file or directory)
    at java.util.zip.ZipFile.open(Native Method)
    at java.util.zip.ZipFile.<init>(ZipFile.java:219)
    at java.util.zip.ZipFile.<init>(ZipFile.java:149)
    at java.util.zip.ZipFile.<init>(ZipFile.java:120)
    at InterpreteSQL.Main.unzip(Main.java:88)
    ... 2 more

Обратите внимание, что другие файлы в ресурсах (help html files ) регулярно открываются в программе.

Это код, который открывает файл:

public static void unzip(String zipFilePath, String unzipDir) throws Exception {
    try{
        ZipFile zipFile = new ZipFile(Main.class.getClassLoader().getResource(zipFilePath).getFile());
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
            while(entries.hasMoreElements()){
...

и вызывается с помощью:

unzip("initialData/compressed.zip", "JRS_directory");

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

Есть идеи о проблеме? Большое спасибо.

1 Ответ

1 голос
/ 19 июня 2020

Вы неправильно используете getResources двумя способами.

  1. Вы просите ресурс без всякой причины преобразовать себя в файл. В вашем запуске eclipse ресурс IS является файлом. Однако при запуске jar это не так (это запись в jar, которая не является файлом). Не вызывайте .getFile () для этих ресурсов; весь смысл абстракции в том, что это может быть вовсе не файл. Может быть запись в банке. Может быть импортирован по сети. Все, что вы знаете: загружайте эти данные из любого места, где вы найдете файлы классов.

Не используйте ZipFile; используйте ZipInputStream с очень похожим API. Затем используйте getResourceAsStream.

Правильная форма - Main.class.getResource(). Избегайте промежуточного уровня загрузчика классов. Это и бессмысленный вызов метода, и в редких случаях он не работает (в определенных контекстах загрузчик классов имеет значение null, вызывая исключение nullpointerexception). Обратите внимание, что эта форма означает, что строка, которую вы передаете, относится к местоположению класса. Если вы этого не хотите, добавьте начальный sla sh.

Пока вы на нем, это ресурсы, которые необходимо закрыть, поэтому давайте воспользуемся конструкцией try-with-resources чтобы гарантировать, что это делается правильно даже в условиях исключений.

Собираем вместе:

try (InputStream raw = Main.class.getResourceAsStream("/" + zipFilePath);
     ZipInputStream zip = new ZipInputStream(raw)) {

    for (ZipEntry entry; (entry = zip.getNextEntry()) != null; ) {
        // do something with entry here
    }
}
...