2017-12-12 18 views
1

"resource/json/templates"フォルダにいくつかのJsonファイルがあります。これらのJsonファイルを読んでみたい。これまでのところ、IDEでプログラムを実行すると、以下のコードスニペットで実行できますが、jarファイルで実行すると失敗します。jarファイルの実行時にリソースフォルダからファイル名のリストを取得する

JSONParser parser = new JSONParser(); 
    ClassLoader loader = getClass().getClassLoader(); 
    URL url = loader.getResource(templateDirectory); 
    String path = url.getPath(); 
    File[] files = new File(path).listFiles(); 
    PipelineTemplateRepo pipelineTemplateRepo = new PipelineTemplateRepoImpl(); 
    File templateFile; 
    JSONObject templateJson; 
    PipelineTemplateVo templateFromFile; 
    PipelineTemplateVo templateFromDB; 
    String templateName; 


    for (int i = 0; i < files.length; i++) { 
    if (files[i].isFile()) { 
     templateFile = files[i]; 
     templateJson = (JSONObject) parser.parse(new FileReader(templateFile)); 
     //Other logic 
    } 
    } 
} 
catch (Exception e) { 
    e.printStackTrace(); 
} 

ご協力いただければ幸いです。

ありがとうございます。

+0

もっと詳しく教えてください。エラーメッセージとは何ですか? jarファイルをどのように作成しましたか? –

+0

申し訳ありませんが、私はMavenビルドでjarファイルを作成しました。そして、「ファイル」はnullになります。 – Juvenik

+0

基本的な答えはできません。 JarファイルはZipファイルですが、実行時に問題のリソースを含むZipファイルの場所を特定できない限り、その内容はリストできません。コードでは、Jarファイルの名前または場所について、コードを可変状態に結合するための前提はありません。代わりに、Jarをビルド/パッケージ化するときに、ファイルリストを生成し、それをよく知られているファイル/場所に保存し、これをJarファイルに保存します。実行時に、このリソースを読んでから、他のファイルのリストが表示されます – MadProgrammer

答えて

1

まず、JarファイルはZipファイルなので、解凍しないで個別のFileを取得することはできません。 Zipファイルには正確にディレクトリがないので、ディレクトリの子を取得するのと同じくらい単純ではありません。

これはちょっと難しいものでしたが、私も好奇心が強いですし、研究した後、私は次のことを考え出しました。

まず、JarにネストされたフラットなZipファイル(resource/json/templates.zip)にリソースを配置し、すべてのZIPエントリが必要なリソースであることがわかっているので、そのzipファイルからすべてのリソースをロードします。これはIDEでも機能します。

String path = "resource/json/templates.zip"; 
ZipInputStream zis = new ZipInputStream(getClass().getResourceAsStream(path)); 
for (ZipEntry ze = zis.getNextEntry(); ze != null; ze = zis.getNextEntry()) { 
    // 'zis' is the input stream and will yield an 'EOF' before the next entry 
    templateJson = (JSONObject) parser.parse(zis); 
} 

また、あなたは、実行中の瓶を取得し、そのエントリを反復処理し、それらのエントリからのストリームを取得し、その後resource/json/templates/の子であるものを集めることができました。注:これは、Jarを実行しているときにのみ機能し、IDEで実行中に何か他のものを実行するためのチェックを追加します。

public void runOrSomething() throws IOException, URISyntaxException { 
    // ... other logic ... 
    final String path = "resource/json/templates/"; 
    Predicate<JarEntry> pred = (j) -> !j.isDirectory() && j.getName().startsWith(path); 

    try (JarFile jar = new Test().getThisJar()) { 
     List<JarEntry> resources = getEntriesUnderPath(jar, pred); 
     for (JarEntry entry : resources) { 
      System.out.println(entry.getName()); 
      try (InputStream is = jar.getInputStream(entry)) { 
       // JarEntry streams are closed when their JarFile is closed, 
       // so you must use them before closing 'jar' 
       templateJson = (JSONObject) parser.parse(is); 
       // ... other logic ... 
      } 
     } 
    } 
} 


// gets ALL the children, not just direct 
// path should usually end in backslash 
public static List<JarEntry> getEntriesUnderPath(JarFile jar, Predicate<JarEntry> pred) 
{ 
    List<JarEntry> list = new LinkedList<>(); 
    Enumeration<JarEntry> entries = jar.entries(); 

    // has to iterate through all the Jar entries 
    while (entries.hasMoreElements()) { 
     JarEntry entry = entries.nextElement(); 
     if (pred.test(entry)) 
      list.add(entry); 
    } 
    return list; 
} 


public JarFile getThisJar() throws IOException, URISyntaxException { 
    URL url = getClass().getProtectionDomain().getCodeSource().getLocation(); 
    return new JarFile(new File(url.toURI())); 
} 

これが役立ちます。

URL url = getClass().getResource("/json"); 
    Path path = Paths.get(url.toURI()); 
    Files.walk(path, 5).forEach(p -> System.out.printf("- %s%n", p.toString())); 

これはjar:file://... URLを使用し、開きます:クラスパスに、jarファイルにディレクトリが(/リソースは、ルートディレクトリです)/ JSONで始まり、それはのような可能性があると仮定すると

0

その上に仮想ファイルシステム。

実際にjarがそのパスを使用しているかどうかを調べます。

希望するとおりに読むことができます。

 BufferedReader in = Files.newBufferedReader(p, StandardCharsets.UTF_8); 
+0

こんにちは、私はこれを試してみましたが、私は次のエラーを取得しています:com.sun.nio.zipfs.ZipFileSystemProvider.getFileSystemで java.nio.file.FileSystemNotFoundException \t(ZipFileSystemProvider.java:171) \tはcom.sunで。 nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:157) \t(java.nio)。file.Paths.get(Paths.java:143) – Juvenik

+0

@Juvenik申し訳ありませんが、私はこれがxtraticのソリューションよりも簡単になることを期待していました。それはそう考えられる。 –

関連する問題