Почему я могу получить действительный URL-адрес от getClass().getResource(), но возвращаемый URL-адрес создает несуществующий файл

Я пытаюсь загрузить некоторые данные в лямбду AWS и использую для этого getClass().getResource(). Это возвращает хороший URL-адрес, который в журналах, по-видимому, распечатывает правдоподобный URL-адрес; однако, когда я пытаюсь создать файл на основе этого пути, я получаю файл, который при вызове .exists() возвращает false.

Если я запускаю приведенный ниже код, первый оператор печати дает «возврат существует: ложь»

Между тем, второй оператор печати дает что-то вроде строк «тестовый путь: /file:/var/task/lib/MyLambda-1.0.jar!/com/my/package/folders/file.end

File test = new File(cFile);
System.out.println("exists: " + test.exists());
System.out.println("test path: " + test.getAbsolutePath());

Не уверен, почему это будет. Если Java находит файл, я бы предположил, что файл существует...


person Darokrithia    schedule 06.08.2019    source источник
comment
Непонятно, что вы спрашиваете. Файл существует или нет?   -  person Phil    schedule 06.08.2019


Ответы (2)


Краткий ответ: не предполагайте, что «путь» URL-адреса является путем к файловой системе.


Я пытаюсь загрузить некоторые данные в лямбду AWS и использую для этого getClass().getResource(). Это возвращает хороший URL-адрес, который в журналах, по-видимому, распечатывает правдоподобный URL-адрес;

Да. (Было бы неплохо, если бы вы показали нам, как выглядит исходный URL-адрес... хотя я могу догадаться.)

Однако, когда я пытаюсь создать файл на основе этого пути, я получаю файл, который при вызове .exists() возвращает false.

ОК, если URL-адрес не имеет протокола «файл:», я бы НЕ ожидал, что это сработает.

Путь в URL — это путь, предназначенный для разрешения обработчиком протокола. Идея состоит в том, что вы используете URL::openStream, чтобы открыть поток для ресурса, указанного в URL-адресе, а затем прочитать его. Обработчик протокола заботится об интерпретации пути (и т. д.) и настройке потока.

  • Для URL-адреса «file:» обработчик протокола разрешает путь в файловой системе и предоставляет вам поток для чтения файла.

  • Для URL-адреса «http:» обработчик протокола устанавливает соединение с сервером, отправляет запрос GET и возвращает вам поток для чтения тела ответа.

  • Для URL-адреса «jar:» обработчик протокола открывает файл JAR, находит запись в файле JAR и передает вам поток для его чтения.

  • И так далее.

Если вы посмотрите на них, то только в случае «файл:» есть разумное ожидание, что обработка компонента пути URL-адреса как имени пути файловой системы может работать.


Глядя на путь в вашем вопросе:

file:/var/task/lib/MyLambda-1.0.jar!/com/my/package/folders/file.end

Я предполагаю, что исходный URL был:

jar:file:/var/task/lib/MyLambda-1.0.jar!/com/my/package/folders/file.end

Итак, что это говорит обработчику протокола «jar:»:

  1. Найдите ресурс, указанный по URL-адресу «file:/var/task/lib/MyLambda-1.0.jar».
  2. Откройте его как поток файла JAR
  3. Найдите запись «/com/my/package/folders/file.end» в пространстве имен файла JAR.
  4. Откройте поток, чтобы прочитать содержимое этой записи.

Обработчик файлового протокола JAR знает, как это сделать. Но (очевидно) класс File не ... потому что этот «путь» не является путем к файловой системе.


Как вы решаете это, зависит от того, что вам действительно нужно.

  • Если вам просто нужен поток для чтения ресурса, используйте вместо этого getClass().getResourceAsStream(...).
  • Если это должен быть файл в файловой системе, вам, возможно, придется получить поток (см. выше), скопировать его во временный файл и использовать File для временного файла.

Если вы делаете это, потому что хотите писать в «файл», я бы посоветовал вам отказаться от этой идеи. Плохая идея для приложения пытаться обновить свои ресурсы. А в некоторых случаях он просто не будет/не может работать.

person Stephen C    schedule 06.08.2019
comment
Это имеет большой смысл. Мне нужно, чтобы это был файл из-за API, который я использую, но мне нужно только прочитать, поэтому я попробую ваше второе предложение. Если это сработает, я отмечу как правильное и еще много чего. Также я не могу отправить исходный URL по причинам, связанным с соглашением о неразглашении. - person Darokrithia; 06.08.2019

Ваш файл test = новый файл (cFile), правильно ли создан ваш cFile с правильным путем? Может быть, последний оператор печати просто указывает на неправильный путь, который вы указали? Но на самом деле у вас там нет файла. Вы вручную проверяли?

person JChris    schedule 06.08.2019
comment
У вас есть права на чтение и запись, ваши обратные косые черты являются двойными обратными косыми чертами? - person JChris; 06.08.2019