У меня есть этот код, который читает все файлы из каталога.
File textFolder = new File("text_directory");
File [] texFiles = textFolder.listFiles( new FileFilter() {
public boolean accept( File file ) {
return file.getName().endsWith(".txt");
}
});
Отлично работает. Он заполняет массив всеми файлами, которые заканчиваются на «.txt» из каталога «text_directory».
Как я могу прочитать содержимое каталога аналогичным образом в пределах файле JAR?
Итак, что я действительно хочу сделать, это перечислить все изображения в моем файле JAR, чтобы я мог загрузить их с помощью:
ImageIO.read(this.getClass().getResource("CompanyLogo.png"));
(Этот работает, потому что «CompanyLogo» «жестко запрограммирован», но количество изображений в файле JAR может быть от 10 до 200 переменной длины.)
РЕДАКТИРОВАТЬ
Итак, я предполагаю, что моей главной проблемой будет: как узнать имя файла JAR, в котором находится мой основной класс?
Конечно, я мог прочитать это, используя java.util.Zip
.
Моя структура такая:
Они похожи на:
my.jar!/Main.class
my.jar!/Aux.class
my.jar!/Other.class
my.jar!/images/image01.png
my.jar!/images/image02a.png
my.jar!/images/imwge034.png
my.jar!/images/imagAe01q.png
my.jar!/META-INF/manifest
Прямо сейчас я могу загрузить, например, "images / image01.png", используя:
ImageIO.read(this.getClass().getResource("images/image01.png));
Но только потому, что я знаю имя файла, в остальном мне приходится загружать их динамически.
Ответы:
Обратите внимание, что в Java 7 вы можете создать
FileSystem
файл из JAR (zip) файла, а затем использовать механизмы обхода и фильтрации каталогов NIO для поиска в нем. Это упростило бы написание кода, обрабатывающего JAR-файлы и "развернутые" каталоги.источник
Код, который работает как для файлов IDE, так и для файлов .jar:
источник
FileSystems.newFileSystem()
принимаетMap<String, ?>
, поэтому вам нужно указать,Collections.emptyMap()
что он должен вернуть типизированный соответствующим образом. Это работает:Collections.<String, Object>emptyMap()
.fileSystem
!walk
методFiles
доступен только в версии 1.8). Единственная проблема заключается в том, что в папке отображается каталог ресурсовFiles.walk(myPath, 1)
, а не только файлы. Думаю, первый элемент можно просто проигнорироватьmyPath = fileSystem.getPath("/resources");
у меня не работает; ничего не находит. В моем случае это должны быть «изображения», а каталог «изображений» определенно включен в мою банку!Эриксона ответ работал отлично:
Вот рабочий код.
И я только что изменил свой метод загрузки следующим образом:
К этому:
источник
Я хотел бы расширить ответ acheron55 , поскольку это очень небезопасное решение по нескольким причинам:
FileSystem
объект.FileSystem
уже объект.Это несколько более безопасное решение:
Нет никакой реальной необходимости синхронизировать по имени файла; можно просто синхронизировать каждый раз один и тот же объект (или создать метод
synchronized
), это чисто оптимизация.Я бы сказал, что это все еще проблемное решение, поскольку в коде могут быть другие части, которые используют
FileSystem
интерфейс для тех же файлов, и это может мешать им (даже в однопоточном приложении).Кроме того, он не проверяет
null
s (например, ongetClass().getResource()
.Этот конкретный интерфейс Java NIO ужасен, так как он представляет глобальный / одноэлементный небезопасный ресурс, а его документация чрезвычайно расплывчата (много неизвестных из-за реализаций, специфичных для поставщика). Результаты могут отличаться для других
FileSystem
поставщиков (не для JAR). Может быть, для этого есть веская причина; Я не знаю, я не исследовал реализации.источник
Предполагая, что ваш проект упакован в Jar (не обязательно верно!), Вы можете использовать ClassLoader.getResource () или findResource () с именем класса (за которым следует .class), чтобы получить jar, содержащий данный класс. Вам нужно будет проанализировать имя банки из возвращаемого URL (не так сложно), что я оставлю в качестве упражнения для читателя :-)
Обязательно проверьте случай, когда класс не является частью jar.
источник
CodeSource
.Я портировал ответ acheron55 на Java 7 и закрыл
FileSystem
объект. Этот код работает в IDE, в файлах jar и в jar во время войны с Tomcat 7; но обратите внимание, что он не работает в банке внутри войны на JBoss 7 (даетFileSystemNotFoundException: Provider "vfs" not installed
, см. также этот пост ). Кроме того, как и исходный код, он не является потокобезопасным, как предполагает errr . По этим причинам я отказался от этого решения; однако, если вы согласны с этими проблемами, вот мой готовый код:источник
Вот метод, который я написал для «запуска всех JUnits в пакете». Вы сможете адаптировать его к своим потребностям.
Изменить: Ах, в этом случае вам может понадобиться этот фрагмент (тот же вариант использования :))
источник
Вот пример использования библиотеки Reflections для рекурсивного сканирования пути к классам с помощью шаблона имени регулярного выражения, дополненного парой привилегий Guava для получения содержимого ресурсов:
Это работает как с банками, так и с разнесенными классами.
источник
Файл jar - это просто zip-файл со структурированным манифестом. Вы можете открыть файл jar с помощью обычных инструментов java zip и таким образом просканировать содержимое файла, раздуть потоки и т. Д. Затем использовать это в вызове getResourceAsStream, и все должно получиться очень круто.
РЕДАКТИРОВАТЬ / после уточнения
Мне потребовалась минута, чтобы вспомнить все мелочи, и я уверен, что есть более чистые способы сделать это, но я хотел убедиться, что я не сумасшедший. В моем проекте image.jpg - это файл в некоторой части основного файла jar. Я получаю загрузчик классов основного класса (SomeClass - это точка входа) и использую его для обнаружения ресурса image.jpg. Затем немного магии потока, чтобы поместить его в эту штуку ImageInputStream, и все в порядке.
источник
new File("blah.JAR")
для создания объекта File, который представляет JAR. Просто замените «blah.JAR» на имя вашего JAR.Учитывая фактический файл JAR, вы можете перечислить его содержимое, используя
JarFile.entries()
. Тем не менее, вам нужно будет знать местоположение файла JAR - вы не можете просто попросить загрузчик классов перечислить все, что он может получить.Вы должны иметь возможность определить местоположение файла JAR на основе возвращенного URL-адреса
ThisClassName.class.getResource("ThisClassName.class")
, но это может быть немного неудобно.источник
new File("baz.jar)
вашем JAR, объект File представлял бы ваш JAR-файл.Некоторое время назад я сделал функцию, которая получает классы из JAR:
источник
источник
Есть две очень полезных утилиты, обе называются JarScan:
www.inetfeedback.com/jarscan
jarscan.dev.java.net
См. Также этот вопрос: JarScan, сканировать все файлы JAR во всех подпапках для определенного класса
источник
Наиболее надежным механизмом для перечисления всех ресурсов в пути к классам в настоящее время является использование этого шаблона с ClassGraph , поскольку он обрабатывает максимально широкий спектр механизмов спецификации пути к классам , включая новую модульную систему JPMS. (Я автор ClassGraph.)
Есть много других способов работать с ресурсами .
источник
Просто другой способ перечисления / чтения файлов из URL-адреса jar, и он делает это рекурсивно для вложенных jar-файлов.
https://gist.github.com/trung/2cd90faab7f75b3bcbaa
источник
Еще один в дорогу:
Это немного более гибко для сопоставления конкретных имен файлов, потому что он использует подстановочные знаки.
Более функциональный стиль:
источник