Ресурс Java как файл

Есть ли способ в Java для создания экземпляра File на ресурсе, извлеченном из jar через загрузчик классов?

В моем приложении используются некоторые файлы из jar (по умолчанию) или из каталога файловой системы, указанного во время выполнения (пользовательский ввод). Я ищу последовательный способ
a) загрузка этих файлов в виде потока
b) перечисление файлов в пользовательском каталоге или каталоге в банке соответственно

Edit: По-видимому, идеальный подход состоял бы в том, чтобы полностью избегать java.io.File. Есть ли способ загрузить каталог из пути к классам и указать его содержимое (файлы/сущности, содержащиеся в нем)?

Ответ 1

ClassLoader.getResourceAsStream и Class.getResourceAsStream - это определенно способ загрузки данных ресурса. Тем не менее, я не верю, что существует какой-либо способ "перечисления" содержимого элемента pathpath.

В некоторых случаях это может быть просто невозможно - например, ClassLoader может генерировать данные "на лету" в зависимости от того, какое имя ресурса он запрашивал. Если вы посмотрите на API ClassLoader (который в основном работает с механизмом pathpath), вы увидите, что вам нечего делать.

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

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

Ответ 2

У меня была та же проблема и я смог использовать следующее:

// Load the directory as a resource
URL dir_url = ClassLoader.getSystemResource(dir_path);
// Turn the resource into a File object
File dir = new File(dir_url.toURI());
// List the directory
String files = dir.list()

Ответ 3

Вот немного кода из одного из моих приложений... Сообщите мне, подходит ли оно вашим потребностям. Вы можете использовать это, если знаете файл, который хотите использовать.

URL defaultImage = ClassA.class.getResource("/packageA/subPackage/image-name.png");
File imageFile = new File(defaultImage.toURI());

Надеюсь, что это поможет.

Ответ 4

Надежный способ создания экземпляра File на ресурсе, извлеченном из банки, заключается в том, чтобы скопировать ресурс в виде потока во временный файл (файл temp будет удален при выходе из JVM):

public static File getResourceAsFile(String resourcePath) {
    try {
        InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(resourcePath);
        if (in == null) {
            return null;
        }

        File tempFile = File.createTempFile(String.valueOf(in.hashCode()), ".tmp");
        tempFile.deleteOnExit();

        try (FileOutputStream out = new FileOutputStream(tempFile)) {
            //copy stream
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
        return tempFile;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}