从JAR文件读取目录内容

时间:2019-12-02 14:29:28

标签: java jar

我正在尝试在webapp中编写代码,而我的类路径中有一个JAR文件。目的是检查目录是否存在于JAR中。如果是,我需要将文件的所有内容保存在HashMap<String, String>中的JAR目录中。密钥是文件名,值是每个文件的内容。

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对象是“ entry”。

现在我不确定为什么direcotry.isDirectory()返回false。它不应该返回true吗?

现在,因为它没有越过第一个异常。我不知道之后会怎样。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

  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转换为文件名,然后询问它是否是目录。当然不是;那甚至都不是文件。您需要进行一些字符串操作以从中提取实际的 file :您只需要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);

如果您希望将其应用于实际目录(类文件,此类文件可能来自dirs而不是文件),则可以执行以下操作:

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

对于一个罐子,实际上只是一个拉链,它会更像:

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是正确的。

答案 1 :(得分:1)

在要搜索的jar(java.nio.file.Path)中输入jarPath,在jar(String)中输入directory作为绝对目录名称,这可能为您服务:

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)