0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

(調査中)Java。JARファイル内にアクセスし、特定フォルダのファイル名のリスト作成

Last updated at Posted at 2024-09-30

JARファイル内にアクセスして、特定のフォルダ内にあるファイルの名前リストを作成するためには、ClassLoaderやgetResourceAsStream()だけでは不十分です。JARファイル内は通常、ファイルシステムのように直接ディレクトリを探索できませんが、java.util.jar.JarFileやClassLoaderを活用してJARファイルのエントリを取得し、特定のフォルダに含まれるファイルのリストを作成できます。

以下は、その具体的な実装方法です。

コード例: JARファイル内の特定フォルダのファイル名をリスト化する

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.util.Enumeration;
import java.util.List;
import java.util.ArrayList;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;

public class JarResourceLister {

    public List<String> listFilesInFolder(String folderName) throws IOException, URISyntaxException {
        List<String> fileNames = new ArrayList<>();
        
        // ClassLoaderを使用してフォルダのURLを取得
        URL folderUrl = getClass().getClassLoader().getResource(folderName);

        if (folderUrl == null) {
            throw new IllegalArgumentException("Folder not found: " + folderName);
        }

        // URLがJARファイル内かどうかを確認
        if ("jar".equals(folderUrl.getProtocol())) {
            // JAR内のリソースを取得
            String jarPath = folderUrl.getPath().substring(5, folderUrl.getPath().indexOf("!"));
            try (JarFile jarFile = new JarFile(Paths.get(new URL(jarPath).toURI()).toFile())) {
                Enumeration<JarEntry> entries = jarFile.entries();

                // JARエントリをイテレートして、指定フォルダに含まれるファイルをリストに追加
                while (entries.hasMoreElements()) {
                    JarEntry entry = entries.nextElement();
                    String entryName = entry.getName();

                    if (entryName.startsWith(folderName) && !entry.isDirectory()) {
                        // フォルダ名の部分を取り除いて、ファイル名のみをリスト化
                        fileNames.add(entryName.substring(folderName.length() + 1));
                    }
                }
            }
        } else {
            // JARではなく、ファイルシステムの場合(ローカルファイルの場合)
            try {
                fileNames = Files.list(Paths.get(folderUrl.toURI()))
                        .filter(Files::isRegularFile)
                        .map(path -> path.getFileName().toString())
                        .collect(Collectors.toList());
            } catch (IOException | URISyntaxException e) {
                throw new RuntimeException("Error reading folder: " + folderName, e);
            }
        }

        return fileNames;
    }

    public static void main(String[] args) {
        try {
            JarResourceLister lister = new JarResourceLister();
            List<String> files = lister.listFilesInFolder("myfolder");

            // ファイル名リストを表示
            files.forEach(System.out::println);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

解説

1. URLからリソースを取得

ClassLoader.getResource()を使って、リソースのURLを取得します。URLのプロトコルがjarであるかどうかを確認し、それに応じて処理を分岐します。

2. JARファイル内のエントリを探索

JarFileを使ってJARファイルの中のエントリを一覧化し、特定フォルダに含まれるファイルのみをリストに追加します。
JarEntryオブジェクトを使って、ディレクトリかファイルかを確認し、ディレクトリではないエントリを抽出します。

3. ローカルファイルシステム対応

ローカルファイルの場合、Files.list()メソッドを使ってディレクトリ内のファイルをリスト化します。これにより、テストや開発中のプロジェクトファイルにも対応できます。
テスト用のディレクトリ
上記のコードでは、myfolderというフォルダ内のファイルをリストアップしています。このフォルダは、プロジェクト内のresourcesディレクトリに配置される想定です。例えば、src/main/resources/myfolder内にファイルがある場合、その中のファイル名がリストとして取得されます。

まとめ

JARファイル内のリソースを扱う際、JARファイルはファイルシステムのようには扱えないため、JarFileを使ってリソースを手動で探索します。
ローカル環境とJARファイル内の両方に対応するコードを用意することで、開発やテスト時に柔軟に動作させることができます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?