簡體   English   中英

從 JAR 文件中讀取目錄內容

[英]Reading Directory Contents From a JAR file

我正在嘗試在 webapp 中編寫代碼,我的類路徑中有一個 JAR 文件。 目的是檢查該目錄是否存在於 JAR 中。 如果是,我需要將 JAR 目錄中文件的所有內容保存在HashMap<String, String> Key 是文件名,value 是每個文件的內容。

File directory = new File(getClass().getClassLoader().getResource(directoryPath).getPath());

System.out.println("PATH IS: " + directory.getPath());

// Check if  dirPth exists and is a valid directory
if (!directory.isDirectory()) {
    throw new AccessException("Directory \"" + directoryPath + "\" not valid");
}

// Obtain a list of all files under the dirPath
File [] fileList = directory.listFiles();

for (File file : fileList) {

    if (file.isFile()) {

        // Read the file
        BufferedReader br = new BufferedReader(new FileReader(file));
        String line = null;
        StringBuilder sb = new StringBuilder();

        while ((line = br.readLine()) != null) {
            sb.append(line);
        }

        br.close();

        // Store the file data in the hash
        entry.put(file.getName(), sb.toString);
    }
}

direcotry.getPath()的輸出是:

文件:\\H:\\apache-tomcat-9.0.27\\lib\\myConfigurationFiles.jar!\\META-INF\\Maintenance\\xmlFiles\\secondary

這是我正在尋找的正確文件夾。

這里的 Map 對象是“條目”。

現在我不確定為什么 direcotry.isDirectory() 返回 false。 它不應該返回true嗎?

現在因為它沒有跨越第一個例外。 我不知道在那之后它會如何表現。 任何幫助,將不勝感激。

  1. getClass()對於這樣的工作是錯誤的方法; 如果有人子類,它會中斷。 正確的方法是改用MyClassName.class

  2. getClassLoader().getResource()也是錯誤的做法; 這在getClassLoader()返回 null 的奇特但可能的情況下中斷。 只需使用getResource並稍微更改路徑(添加前導斜杠,或者寫入相對於您的類文件的路徑)。

  3. 您將字符串file:\\H:\\apache-tomcat-9.0.27\\lib\\myConfigurationFiles.jar!\\META-INF\\Maintenance\\xmlFiles\\secondary轉換為文件名,然后詢問它是否是目錄。 當然不是; 那甚至不是一個文件。 您需要進行一些字符串操作以從中提取實際文件:您只需要H:\\apache-tomcat-9.0.27\\lib\\myConfigurationFiles.jar ,將其提供給java.nio.file API,然后使用詢問它是否是一個文件(它永遠不會是一個目錄;jar 不是目錄)。

  4. 請注意,如果您正在讀取的資源不是 jar,這將不起作用。 請注意,類加載 API 是抽象的:您可能會發現自己處於從頭開始生成源文件或從數據庫加載的場景中, getResource方法生成更多奇特的 URL 以進行引導。 因此,這種代碼根本就行不通。 首先確保沒問題。

因此:

String urlAsString = MyClassName.class.getResource("MyClassName.class").toString(); // produces a link to yourself.

int start = urlAsString.startsWith("file:jar:") ? 8 : urlAsString.startsWith("file:") ? 4 : 0;
int end = urlAsString.lastIndexOf('!');
String jarFileLoc = urlAsString.substring(start, end);

如果您希望這適用於實際目錄(類文件等可以來自目錄而不是文件),您可以執行以下操作:

var map = new HashMap<String, String>();

Path root = Paths.get(jarFileLoc);

Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        String content = new String(Files.readAllBytes(file), StandardCharsets.UTF_8);
        map.put(root.relativize(file), content);
    }
});

對於一個 jar,它實際上只是一個 zip,它更像是:

var map = new HashMap<String, String>();
Path root = Paths.get(jarFileLoc);
try (var fileIn = Files.newInputStream(root)) {
    ZipInputStream zip = new ZipInputStream(fileIn);
    for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) {
        String content = new String(zip.readAllBytes(), StandardCharsets.UTF_8);
        map.put(entry.getName(), content);
    }
}

確保您知道字符集是什么並且 UTF_8 在這里是正確的。

給定要搜索的 jar ( jarPath ) 的java.nio.file.Path和 jar ( directory ) 中絕對目錄名稱的String ,這可能對您jarPath

Map<String, String> map = new HashMap<>();
try (FileSystem fs = FileSystems.newFileSystem(jarPath, null)) {
    Path dir = fs.getPath(directory);
    if (Files.exists(dir)) {
        Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                throws IOException {
                map.put(file.toString(), Files.readString(file));
                return super.visitFile(file, attrs);
            }
        });
    }
}

Files.readString可用於 Java 11+。 對於早期版本,請使用:

new String(Files.readAllBytes(file), StandardCharsets.UTF_8)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM