Bir JAR dosyası içindeki dosyalar nasıl listelenir?


114

Bir dizindeki tüm dosyaları okuyan bu koda sahibim.

    File textFolder = new File("text_directory");

    File [] texFiles = textFolder.listFiles( new FileFilter() {
           public boolean accept( File file ) {
               return file.getName().endsWith(".txt");
           }
    });

Harika çalışıyor. Diziyi, "text_directory" dizininden ".txt" ile biten tüm dosyalarla doldurur.

Bir JAR dosyası içindeki bir dizinin içeriğini benzer şekilde nasıl okuyabilirim ?

Yani gerçekten yapmak istediğim şey, JAR dosyamın içindeki tüm resimleri listelemek, böylece onları şu şekilde yükleyebilirim:

ImageIO.read(this.getClass().getResource("CompanyLogo.png"));

(Bu işe yarıyor çünkü "CompanyLogo" "kodlanmış" ancak JAR dosyasındaki görüntü sayısı 10 ila 200 değişken uzunlukta olabilir.)

DÜZENLE

Sanırım asıl sorunum şu olurdu: Ana sınıfımın yaşadığı JAR dosyasının adını nasıl öğrenebilirim ?

Bunu kullanarak okuyabileceğime izin verildi java.util.Zip.

Yapım şöyle:

Onlar ... gibi:

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 

Şu anda şunu kullanarak örneğin "images / image01.png" dosyasını yükleyebiliyorum:

    ImageIO.read(this.getClass().getResource("images/image01.png));

Ama sadece dosya adını bildiğim için, geri kalanı için onları dinamik olarak yüklemem gerekiyor.


Sadece bir düşünce - neden resimleri ayrı bir dosyaya sıkıştırıp sınıfınızdaki girişleri başka bir kavanozda okumuyorsunuz?
Vineet Reynolds

3
Çünkü dağıtım / kurulum için "ekstra" bir adıma ihtiyaç duyacaktır. :( Biliyorsunuz, son kullanıcılar.
OscarRyz

Kavanozu sizin oluşturduğunuz göz önüne alındığında, herhangi bir numara denemek yerine içindeki dosyaların listesini de dahil edebilirsiniz.
Tom Hawtin - tackline

Şey, yanılıyor olabilirim ama kavanozlar başka kavanozların içine gömülebilir. Tek kavanoz (TM) paketleme çözümü ibm.com/developerworks/java/library/j-onejar bu temelde çalışır. Bunun dışında, sizin durumunuzda yetenek yükü sınıflarına ihtiyacınız yoktur.
Vineet Reynolds

Yanıtlar:


91
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'de FileSystemJAR (zip) dosyasından bir tane oluşturabileceğinizi ve ardından NIO'nun dizin yürüyüş ve filtreleme mekanizmalarını kullanarak arama yapabileceğinizi unutmayın. Bu, JAR'ları ve "patlatılmış" dizinleri işleyen kod yazmayı kolaylaştırır.


hey teşekkürler ... bunu birkaç saattir yapmanın bir yolunu arıyordum !!
Newtopian

9
Evet, bu jar dosyası içindeki tüm girişleri listelemek istersek bu kod çalışır. Ancak, jar içinde bir alt dizini listelemek istersem, örneğin, example.jar / dir1 / dir2 / , bu alt dizindeki tüm dosyaları nasıl doğrudan listeleyebilirim? Veya bu jar dosyasını açmam gerekiyor mu? Yardımın için çok minnettarım!
Ensom Hodder

Bahsedilen Java 7 yaklaşımı @ acheron55'in cevabında listelenmiştir .
Vadzim

@Vadzim acheron55'in cevabının Java 7 için olduğundan emin misiniz? Files.walk () veya java.util.Stream'i Java 7'de bulamadım
Bruce Paz

@BruceSun, java 7'de bunun yerine Files.walkFileTree (...) kullanabilirsiniz .
Vadzim

80

Hem IDE'ler hem de .jar dosyaları için çalışan kod:

import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.stream.*;

public class ResourceWalker {
    public static void main(String[] args) throws URISyntaxException, IOException {
        URI uri = ResourceWalker.class.getResource("/resources").toURI();
        Path myPath;
        if (uri.getScheme().equals("jar")) {
            FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.<String, Object>emptyMap());
            myPath = fileSystem.getPath("/resources");
        } else {
            myPath = Paths.get(uri);
        }
        Stream<Path> walk = Files.walk(myPath, 1);
        for (Iterator<Path> it = walk.iterator(); it.hasNext();){
            System.out.println(it.next());
        }
    }
}

5
FileSystems.newFileSystem()a alır Map<String, ?>, bu nedenle Collections.emptyMap()uygun şekilde yazılmış bir tane döndürmesi gerektiğini belirtmeniz gerekir . Bu çalışır: Collections.<String, Object>emptyMap().
Zero3

6
Fantastik!!! ancak URI uri = Sınıfım.class.getResource ("/ kaynaklar"). toURI (); MyClass.class.getClassLoader (). getResource ("/ kaynaklar"). toURI (); yani getClassLoader (). Aksi takdirde benim için çalışmıyordu.
EMM

8
Kapatmayı unutma fileSystem!
gmjonker

3
Bu, 1.8 için ilk cevap olmalıdır ( walkyöntem Filesyalnızca 1.8'de mevcuttur). Tek sorun, kaynaklar dizininin Files.walk(myPath, 1)yalnızca dosyalarda değil içinde görünmesidir . Sanırım ilk unsur basitçe göz ardı edilebilir
toto_tico

4
myPath = fileSystem.getPath("/resources");benim için çalışmıyor; hiçbir şey bulamıyor. Benim durumumda "resimler" olmalı ve "resimler" dizini kesinlikle kavanozuma dahil edilmiştir!
phip1611

21

Ericson'ın cevabı mükemmel çalıştı:

İşte çalışma kodu.

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() ] );

Ve yükleme yöntemimi bundan değiştirdim:

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

Buna:

String  [] webimages = ...

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

9

Birkaç nedenden ötürü çok güvenli olmayan bir çözüm olduğu için acheron55'in cevabını genişletmek istiyorum :

  1. FileSystemNesneyi kapatmaz .
  2. FileSystemNesnenin zaten var olup olmadığını kontrol etmez .
  3. İş parçacığı için güvenli değil.

Bu biraz daha güvenli bir çözüm:

private static ConcurrentMap<String, Object> locks = new ConcurrentHashMap<>();

public void walk(String path) throws Exception {

    URI uri = getClass().getResource(path).toURI();
    if ("jar".equals(uri.getScheme()) {
        safeWalkJar(path, uri);
    } else {
        Files.walk(Paths.get(path));
    }
}

private void safeWalkJar(String path, URI uri) throws Exception {

    synchronized (getLock(uri)) {    
        // this'll close the FileSystem object at the end
        try (FileSystem fs = getFileSystem(uri)) {
            Files.walk(fs.getPath(path));
        }
    }
}

private Object getLock(URI uri) {

    String fileName = parseFileName(uri);  
    locks.computeIfAbsent(fileName, s -> new Object());
    return locks.get(fileName);
}

private String parseFileName(URI uri) {

    String schemeSpecificPart = uri.getSchemeSpecificPart();
    return schemeSpecificPart.substring(0, schemeSpecificPart.indexOf("!"));
}

private FileSystem getFileSystem(URI uri) throws IOException {

    try {
        return FileSystems.getFileSystem(uri);
    } catch (FileSystemNotFoundException e) {
        return FileSystems.newFileSystem(uri, Collections.<String, String>emptyMap());
    }
}   

Dosya adı üzerinden senkronizasyon yapmaya gerçekten gerek yoktur; her seferinde aynı nesne üzerinde basitçe senkronize edilebilir (veya yöntemi yapabilir synchronized), bu tamamen bir optimizasyondur.

Kodda FileSystemaynı dosyalar üzerinde arayüzü kullanan başka parçalar olabileceğinden ve bunlara müdahale edebileceğinden (tek iş parçacıklı bir uygulamada bile) bunun hala sorunlu bir çözüm olduğunu söyleyebilirim.
Ayrıca, s'leri de kontrol etmez null(örneğin getClass().getResource(),.

Bu özel Java NIO arabirimi, küresel / tekil iş parçacığı güvenli olmayan bir kaynak sunduğundan ve dokümantasyonu son derece belirsiz olduğundan (sağlayıcıya özgü uygulamalar nedeniyle birçok bilinmeyen) oldukça korkunçtur. Sonuçlar diğer FileSystemsağlayıcılar için farklılık gösterebilir (JAR değil). Belki böyle olmasının iyi bir nedeni vardır; Bilmiyorum, uygulamaları araştırmadım.


1
FS gibi harici kaynakların senkronizasyonunun tek bir VM içinde pek bir anlamı yoktur. Sanal makinenizin dışından ona erişen başka uygulamalar olabilir. Ayrıca, kendi uygulamanızın içinde bile, dosya adlarına dayalı kilitlemeniz kolayca atlanabilir. Bu şeylerle, dosya kilitleme gibi işletim sistemi senkronizasyon mekanizmalarına güvenmek daha iyidir.
Espinosa

@Espinosa Dosya adı kilidi mekanizması tamamen atlanabilir; Benim cevabım da yeterince güvenli değil, ancak Java NIO'ları ile minimum çabayla elde edebileceğiniz en fazla şeyin bu olduğuna inanıyorum. Müşteri tabanlı bir uygulama oluşturmadığınız sürece kilitleri yönetmek için işletim sistemine güvenmek veya hangi uygulamaların hangi dosyalara eriştiğini kontrol etmemek kötü bir uygulamadır IMHO, örneğin bir metin editörü. Kilitleri kendi başınıza yönetmemek, ya istisnaların atılmasına ya da iş parçacıklarının uygulamayı engellemesine neden olur - her ikisinden de kaçınılmalıdır.
Eyal Roth

8

Sanırım asıl sorunum, ana sınıfımın yaşadığı kavanozun adını nasıl bileceğim.

Projenizin bir Jar içinde paketlendiğini varsayarsak (doğru olması gerekmez!), Belirli bir sınıfı içeren jar'i almak için ClassLoader.getResource () veya findResource () sınıf adıyla (ardından .class) kullanabilirsiniz. Jar adını, döndürülen URL'den ayrıştırmanız gerekecek (o kadar da zor değil), bunu okuyucuya alıştırma olarak bırakacağım :-)

Sınıfın bir kavanozun parçası olmadığı durumu test ettiğinizden emin olun.


1
huh - bunun yorum yapılmadan modifiye edilmiş olması ilginç ... Yukarıdaki tekniği her zaman kullanıyoruz ve gayet iyi çalışıyor.
Kevin Günü

Eski bir konu, ama bana göre bu iyi bir hack gibi görünüyor. Sıfıra geri oy verildi :)
Tuukka Mustonen

Oy verildi, çünkü bu, bir sınıfın bir CodeSource.
Monica 2331977

7

Ben taşınmış ettik acheron55 yanıtını Java 7'ye ve kapalı FileSystemnesne. Bu kod IDE'lerde, jar dosyalarında ve Tomcat 7'deki bir savaşın içindeki bir kavanozda çalışır; ama yok not olduğunu değil JBoss 7'de bir savaş içinde bir kavanozun içinde çalışmak (o verir FileSystemNotFoundException: Provider "vfs" not installed, ayrıca bkz Bu yayını ). Ayrıca, orijinal kod gibi, errr tarafından önerildiği gibi iş parçacığı açısından güvenli değildir . Bu nedenlerle bu çözümü terk ettim; ancak, bu sorunları kabul ederseniz, işte hazır kodum:

import java.io.IOException;
import java.net.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections;

public class ResourceWalker {

    public static void main(String[] args) throws URISyntaxException, IOException {
        URI uri = ResourceWalker.class.getResource("/resources").toURI();
        System.out.println("Starting from: " + uri);
        try (FileSystem fileSystem = (uri.getScheme().equals("jar") ? FileSystems.newFileSystem(uri, Collections.<String, Object>emptyMap()) : null)) {
            Path myPath = Paths.get(uri);
            Files.walkFileTree(myPath, new SimpleFileVisitor<Path>() { 
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    System.out.println(file);
                    return FileVisitResult.CONTINUE;
                }
            });
        }
    }
}

5

İşte "tüm JUnit'leri bir paket altında çalıştır" için yazdığım bir yöntem. İhtiyaçlarınıza göre uyarlayabilmelisiniz.

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));
            }
        }
    }
}

Düzenleme: Ah, bu durumda, bu pasajı da isteyebilirsiniz (aynı kullanım durumu :))

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);
    }
}

1
Sanırım en büyük sorun, ilk etapta jar dosyasının adını bilmek. Ana Sınıfın yaşadığı kavanozdur.
OscarRyz

5

Burada, kaynak içeriklerini getirmek için birkaç Guava ayrıcalığı ile artırılmış normal ifade adı kalıbına göre sınıf yolunu yinelemeli olarak taramak için Yansımalar kitaplığı kullanma örneği verilmiştir :

Reflections reflections = new Reflections("com.example.package", new ResourcesScanner());
Set<String> paths = reflections.getResources(Pattern.compile(".*\\.template$"));

Map<String, String> templates = new LinkedHashMap<>();
for (String path : paths) {
    log.info("Found " + path);
    String templateName = Files.getNameWithoutExtension(path);
    URL resource = getClass().getClassLoader().getResource(path);
    String text = Resources.toString(resource, StandardCharsets.UTF_8);
    templates.put(templateName, text);
}

Bu hem kavanozlarla hem de patlatılmış sınıflarla çalışır.


Yansımaların hala Java 9 ve üstünü desteklemediğine dikkat edin: github.com/ronmamo/reflections/issues/186 . Orada rakip kütüphanelere bağlantılar var.
Vadzim

3

Bir jar dosyası, yapılandırılmış bir bildirim içeren bir zip dosyasıdır. Jar dosyasını her zamanki java zip araçlarıyla açabilir ve dosya içeriğini bu şekilde tarayabilir, akışları şişirebilir, vb. Sonra bunu bir getResourceAsStream çağrısında kullanın ve hepsi hunky dory olmalıdır.

DÜZENLE / açıklamadan sonra

Tüm parçaları hatırlamam bir dakikamı aldı ve eminim bunu yapmanın daha temiz yolları vardır, ama deli olmadığımı görmek istedim. Benim projemde image.jpg ana jar dosyasının bir kısmında yer alan bir dosyadır. Ana sınıfın sınıf yükleyicisini alıyorum (SomeClass giriş noktasıdır) ve image.jpg kaynağını keşfetmek için kullanıyorum. Sonra onu bu ImageInputStream şeyine sokmak için biraz akış sihri ve her şey yolunda.

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

Bu kavanoz, ana programı ve kaynakları içerir. Öz kavanozdan nasıl bahsedebilirim? jar dosyasının içinden?
OscarRyz

JAR dosyasına başvurmak için, Dize olarak "blah.JAR" kullanın. new File("blah.JAR")Örneğin, JAR'ı temsil eden bir File nesnesi oluşturmak için kullanabilirsiniz . "Blah.JAR" kısmını JAR'ınızın adıyla değiştirin.
Thomas Owens

Zaten tükenmekte olduğunuz kavanozla aynıysa, sınıf yükleyici kavanozun içindeki şeyleri görebilmelidir ... Başlangıçta ne yapmaya çalıştığınızı yanlış anladım.
Mikeb

2
Evet, zaten buna sahibim, sorun şu gibi bir şeye ihtiyacım olduğunda: "... getResourceAsStream (" *. Jpg "); ..." Yani, dinamik olarak içerdiği dosyaları listeleyin.
OscarRyz

3

Gerçek bir JAR dosyası verildiğinde, içeriğini kullanarak listeleyebilirsiniz JarFile.entries(). Yine de JAR dosyasının konumunu bilmeniz gerekecek - sınıf yükleyiciden alabileceği her şeyi listelemesini isteyemezsiniz.

Döndürülen URL'ye göre JAR dosyasının konumunu bulabilmeniz gerekir ThisClassName.class.getResource("ThisClassName.class"), ancak bu biraz karmaşık olabilir.


Cevabınızı okurken başka bir soru ortaya çıktı. Çağrıyı ne verir: this.getClass (). GetResource ("/ my_directory"); Dizin olarak .... kullanılabilecek bir URL döndürmelidir? Nahh ... bırak deneyeyim.
OscarRyz

JAR'ın konumunu her zaman bilirsiniz - "." İçinde. JAR'ın adının bir şey olduğu bilindiği sürece, bir yerde bir String sabiti kullanabilirsiniz. Şimdi, eğer insanlar JAR'ın adını değiştirmeye giderse ...
Thomas Owens

@Thomas: Bu, uygulamayı mevcut dizinden çalıştırdığınızı varsayar. "Java -jar foo / bar / baz.jar" ın nesi var?
Jon Skeet

İnanıyorum ki (ve bunu doğrulamalıyım), Jar'nızda bu kod varsa new File("baz.jar), File nesnesi JAR dosyanızı temsil eder.
Thomas Owens

@Thomas: Öyle olduğuna inanmıyorum. Bunun sürecin mevcut çalışma dizinine göre olacağına inanıyorum. Yine de kontrol etmem gerekecek :)
Jon Skeet

3

Bir süre önce JAR'ın içinden sınıfsızlık alan bir işlev yaptım:

public static Class[] getClasses(String packageName) 
throws ClassNotFoundException{
    ArrayList<Class> classes = new ArrayList<Class> ();

    packageName = packageName.replaceAll("\\." , "/");
    File f = new File(jarName);
    if(f.exists()){
        try{
            JarInputStream jarFile = new JarInputStream(
                    new FileInputStream (jarName));
            JarEntry jarEntry;

            while(true) {
                jarEntry=jarFile.getNextJarEntry ();
                if(jarEntry == null){
                    break;
                }
                if((jarEntry.getName ().startsWith (packageName)) &&
                        (jarEntry.getName ().endsWith (".class")) ) {
                    classes.add(Class.forName(jarEntry.getName().
                            replaceAll("/", "\\.").
                            substring(0, jarEntry.getName().length() - 6)));
                }
            }
        }
        catch( Exception e){
            e.printStackTrace ();
        }
        Class[] classesA = new Class[classes.size()];
        classes.toArray(classesA);
        return classesA;
    }else
        return null;
}

2
public static ArrayList<String> listItems(String path) throws Exception{
    InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(path);
    byte[] b = new byte[in.available()];
    in.read(b);
    String data = new String(b);
    String[] s = data.split("\n");
    List<String> a = Arrays.asList(s);
    ArrayList<String> m = new ArrayList<>(a);
    return m;
}

3
Bu kod parçacığı sorunu çözebilir ancak soruyu neden veya nasıl yanıtladığını açıklamaz. Lütfen kodunuz için bir açıklamaya yer gerçekten Yayınınızla kalitesini artırmak için yardımcı olarak,. Gelecekte okuyucular için soruyu yanıtladığınızı ve bu kişilerin kod önerinizin nedenlerini bilmeyebileceklerini unutmayın.
Samuel Philipp

Kodu bir jar dosyasından çalıştırdığımızda veriler boştur.
Aguid


1

Sınıf yolundaki tüm kaynakları listelemek için en sağlam mekanizma, şu anda bu modeli ClassGraph ile kullanmaktır , çünkü yeni JPMS modül sistemi dahil olmak üzere mümkün olan en geniş sınıf yolu spesifikasyon mekanizmaları dizisini işler . (ClassGraph'ın yazarıyım.)

Ana sınıfımın yaşadığı JAR dosyasının adını nasıl öğrenebilirim?

URI mainClasspathElementURI;
try (ScanResult scanResult = new ClassGraph().whitelistPackages("x.y.z")
        .enableClassInfo().scan()) {
    mainClasspathElementURI =
            scanResult.getClassInfo("x.y.z.MainClass").getClasspathElementURI();
}

Bir JAR dosyası içindeki bir dizinin içeriğini benzer şekilde nasıl okuyabilirim?

List<String> classpathElementResourcePaths;
try (ScanResult scanResult = new ClassGraph().overrideClasspath(mainClasspathElementURI)
        .scan()) {
    classpathElementResourcePaths = scanResult.getAllResources().getPaths();
}

Orada kaynaklarla uğraşmak pek çok yöntem de.


1
Çok güzel paket, Scala projemde rahatlıkla kullanılabilir, teşekkürler.
zslim

0

Dosyaları bir jar URL'sinden listelemenin / okumanın farklı bir yolu ve iç içe geçmiş kavanozlar için yinelemeli olarak yapıyor

https://gist.github.com/trung/2cd90faab7f75b3bcbaa

URL urlResource = Thead.currentThread().getContextClassLoader().getResource("foo");
JarReader.read(urlResource, new InputStreamCallback() {
    @Override
    public void onFile(String name, InputStream is) throws IOException {
        // got file name and content stream 
    }
});

0

Yol için bir tane daha:

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;

import static java.nio.file.FileSystems.newFileSystem;
import static java.util.Collections.emptyMap;

public class ResourceWalker {
  private static final PathMatcher FILE_MATCHER =
      FileSystems.getDefault().getPathMatcher( "glob:**.ttf" );

  public static List<Path> walk( final String directory )
      throws URISyntaxException, IOException {
    final List<Path> filenames = new ArrayList<>();
    final var resource = ResourceWalker.class.getResource( directory );

    if( resource != null ) {
      final var uri = resource.toURI();
      final var path = uri.getScheme().equals( "jar" )
          ? newFileSystem( uri, emptyMap() ).getPath( directory )
          : Paths.get( uri );
      final var walk = Files.walk( path, 10 );

      for( final var it = walk.iterator(); it.hasNext(); ) {
        final Path p = it.next();
        if( FILE_MATCHER.matches( p ) ) {
          filenames.add( p );
        }
      }
    }

    return filenames;
  }
}

Bu, belirli dosya adlarını eşleştirmek için biraz daha esnektir çünkü joker karakter genelleme kullanır.


Daha işlevsel bir tarz:

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.util.function.Consumer;

import static java.nio.file.FileSystems.newFileSystem;
import static java.util.Collections.emptyMap;

/**
 * Responsible for finding file resources.
 */
public class ResourceWalker {
  private static final PathMatcher FILE_MATCHER =
      FileSystems.getDefault().getPathMatcher( "glob:**.ttf" );

  public static void walk( final String dirName, final Consumer<Path> f )
      throws URISyntaxException, IOException {
    final var resource = ResourceWalker.class.getResource( dirName );

    if( resource != null ) {
      final var uri = resource.toURI();
      final var path = uri.getScheme().equals( "jar" )
          ? newFileSystem( uri, emptyMap() ).getPath( dirName )
          : Paths.get( uri );
      final var walk = Files.walk( path, 10 );

      for( final var it = walk.iterator(); it.hasNext(); ) {
        final Path p = it.next();
        if( FILE_MATCHER.matches( p ) ) {
          f.accept( p );
        }
      }
    }
  }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.