Как перечислить файлы в файле JAR?

Худшая часть - то, что, когда Вы пишете новый код, его твердое, чтобы знать, если Вы случайно представили больше предупреждений, с тех пор существуют так многие, Вы просто игнорируете их так или иначе.

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

107
задан 030 9 January 2019 в 21:38
поделиться

7 ответов

CodeSource src = MyClass.class.getProtectionDomain().getCodeSource();
if (src != null) {
  URL jar = src.getLocation();
  ZipInputStream zip = new ZipInputStream(jar.openStream());
  while(true) {
    ZipEntry e = zip.getNextEntry();
    if (e == null)
      break;
    String name = e.getName();
    if (name.startsWith("path/to/your/dir/")) {
      /* Do something with this entry. */
      ...
    }
  }
} 
else {
  /* Fail... */
}

Обратите внимание, что в Java 7 вы можете создать FileSystem из файла JAR (zip), а затем использовать механизмы просмотра каталогов и фильтрации NIO для поиска в нем. Это упростило бы написание кода, обрабатывающего JAR-файлы и "развернутые" каталоги.

84
ответ дан 24 November 2019 в 03:40
поделиться

Имея фактический файл JAR, вы можете перечислить его содержимое с помощью JarFile. записи () . Однако вам нужно будет знать местоположение файла JAR - вы не можете просто попросить загрузчик классов перечислить все, что он может получить.

Вы должны иметь возможность определить местоположение файла JAR на основе возвращенного URL из ThisClassName.class.getResource ("ThisClassName.class") , но это может быть немного неудобно.

3
ответ дан 24 November 2019 в 03:40
поделиться

Файл jar - это просто файл zip со структурированным манифестом. Вы можете открыть файл jar с помощью обычных инструментов java zip и таким образом просканировать содержимое файла, раздуть потоки и т. Д. Затем использовать это в вызове getResourceAsStream, и все должно получиться очень громоздко.

EDIT / после уточнения

] Мне потребовалась минута, чтобы вспомнить все мелочи, и я уверен, что есть более чистые способы сделать это, но я хотел убедиться, что я не сумасшедший. В моем проекте image.jpg - это файл в некоторой части основного файла jar. Я получаю загрузчик классов основного класса (SomeClass - это точка входа) и использую его для обнаружения ресурса image.jpg. Затем немного магии потока, чтобы поместить его в эту штуку ImageInputStream, и все в порядке.

InputStream inputStream = SomeClass.class.getClassLoader().getResourceAsStream("image.jpg");
JPEGImageReaderSpi imageReaderSpi = new JPEGImageReaderSpi();
ImageReader ir = imageReaderSpi.createReaderInstance();
ImageInputStream iis = new MemoryCacheImageInputStream(inputStream);
ir.setInput(iis);
....
ir.read(0); //will hand us a buffered image
3
ответ дан 24 November 2019 в 03:40
поделиться

Итак, я предполагаю, что моя основная проблема будет в том, как узнать имя jar-файла, в котором находится мой основной класс.

Предполагая, что ваш проект упакован в Jar (не обязательно верно! ), вы можете использовать ClassLoader.getResource () или findResource () с именем класса (за которым следует .class), чтобы получить банку, содержащую данный класс. Вам нужно будет проанализировать имя jar-файла из возвращаемого URL (не так сложно), что я оставлю как упражнение для читателя: -)

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

6
ответ дан 24 November 2019 в 03:40
поделиться

Вот метод, который я написал для «запуска всех JUnits в пакете». Вы сможете адаптировать его под свои нужды.

private static void findClassesInJar(List<String> classFiles, String path) throws IOException {
    final String[] parts = path.split("\\Q.jar\\\\E");
    if (parts.length == 2) {
        String jarFilename = parts[0] + ".jar";
        String relativePath = parts[1].replace(File.separatorChar, '/');
        JarFile jarFile = new JarFile(jarFilename);
        final Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
            final JarEntry entry = entries.nextElement();
            final String entryName = entry.getName();
            if (entryName.startsWith(relativePath)) {
                classFiles.add(entryName.replace('/', File.separatorChar));
            }
        }
    }
}

Изменить: Ах, в этом случае вам может понадобиться и этот фрагмент (тот же вариант использования :))

private static File findClassesDir(Class<?> clazz) {
    try {
        String path = clazz.getProtectionDomain().getCodeSource().getLocation().getFile();
        final String codeSourcePath = URLDecoder.decode(path, "UTF-8");
        final String thisClassPath = new File(codeSourcePath, clazz.getPackage().getName().repalce('.', File.separatorChar));
    } catch (UnsupportedEncodingException e) {
        throw new AssertionError("impossible", e);
    }
}
5
ответ дан 24 November 2019 в 03:40
поделиться

ответ Эриксона работал отлично:

Вот рабочий код.

CodeSource src = MyClass.class.getProtectionDomain().getCodeSource();
List<String> list = new ArrayList<String>();

if( src != null ) {
    URL jar = src.getLocation();
    ZipInputStream zip = new ZipInputStream( jar.openStream());
    ZipEntry ze = null;

    while( ( ze = zip.getNextEntry() ) != null ) {
        String entryName = ze.getName();
        if( entryName.startsWith("images") &&  entryName.endsWith(".png") ) {
            list.add( entryName  );
        }
    }

 }
 webimages = list.toArray( new String[ list.size() ] );

И я только что изменил свой метод загрузки с этого:

File[] webimages = ... 
BufferedImage image = ImageIO.read(this.getClass().getResource(webimages[nextIndex].getName() ));

На это:

String  [] webimages = ...

BufferedImage image = ImageIO.read(this.getClass().getResource(webimages[nextIndex]));
20
ответ дан 24 November 2019 в 03:40
поделиться

Есть две очень полезные утилиты, обе называются JarScan:

  1. www.inetfeedback.com/jarscan

  2. jarscan.dev.java.net

См. Также этот вопрос: JarScan, сканировать все Файлы JAR во всех подпапках для определенного класса

1
ответ дан 24 November 2019 в 03:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: