1

我调用了一个希望返回 true 的 HashMap 的 containsKey 方法。如果我将程序编译为 .class 文件并像这样运行它,它会返回 true,但是如果我构建一个 JAR,那么由于我无法理解的原因,相同的调用会返回 false。

我已经调试了 .class 和 JAR 版本(使用远程连接的 JAR,如http://www.eclipsezone.com/eclipse/forums/t53459.html中所述),在这两种情况下,HashMap 似乎都包含我正在尝试检查的关键。

HashMap 使用 URI 对象作为键。以下是每个调试会话中显示的变量内容:

当作为 .class 文件运行时

哈希映射键:java.net.URI = file:/E:/SSD%20App%20Libraries/Google%20Drive/Programming/Bet%20Matching/Java%20Sim/target/classes/simfiles/paytables/

URIToCheck:java.net.URI = file:///E:/SSD%20App%20Libraries/Google%20Drive/Programming/Bet%20Matching/Java%20Sim/target/classes/simfiles/paytables/

结果:GameTreeItemsMap.containsKey(URIToCheck)true

作为 JAR 运行时

哈希映射键:java.net.URI = jar:file:/E:/SSD%20App%20Libraries/Google%20Drive/Programming/Bet%20Matching/Java%20Sim/out/artifacts/JavaSim_jar/Java%20Sim.jar!/simfiles/paytables/

URIToCheck:java.net.URI = jar:file:///E:/SSD%2520App%2520Libraries/Google%2520Drive/Programming/Bet%2520Matching/Java%2520Sim/out/artifacts/JavaSim_jar/Java%2520Sim.jar!/simfiles/paytables/

结果:GameTreeItemsMap.containsKey(URIToCheck)false

我希望该方法true在这两种情况下都会返回。URI 在 JAR 中的行为是否有所不同?这是怎么回事?

提前感谢您的帮助!

编辑 1 正如向我指出的那样,JAR 案例中的 URIToCheck 被双重编码(%2520 而不是 %20)。这是生成 URIToCheck 的代码。我使用walkFileTree方法。

        Files.walkFileTree(paytableHomePath, new SimpleFileVisitor<Path>(){
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {

                Path parentPath = dir.getParent();

                URI parentURIToCheck = parentPath.toUri();

                boolean testContain = GameTreeItemsMap.containsKey(parentURIToCheck);

                return FileVisitResult.CONTINUE;
            }

在 JAR 的情况下,URIparentURIToCheck是双重编码的(用 %5250 表示应该有 %20 的空格),而在 .class 的情况下,这不会发生。知道为什么吗?

4

1 回答 1

1

这与 HashMap 无关。您似乎在 Java 的Zip File System Provider中发现了一个错误,即它将 Path 转换为双重编码的 URI。

我找不到它的现有错误,所以我提交了一个。(有这个相关的错误,我怀疑它的修复是造成这个错误的原因。) 更新:这是Java 错误 8131067

这是我为演示该问题而编写的程序,使用 Java 1.8.0_45-b14。将路径中包含一个或多个空格的 .jar 文件作为第一个命令行参数传递。

import java.util.Map;
import java.util.Collections;
import java.net.URI;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;

public class JarPathTest {
    public static void main(String[] args)
    throws IOException {

        Path zip = Paths.get(args[0]);

        URI zipURI = URI.create("jar:" + zip.toUri());
        System.out.println(zipURI);

        Map<String, String> env = Collections.emptyMap();

        try (FileSystem fs = FileSystems.newFileSystem(zipURI, env)) {
            Path root = fs.getPath("/");
            System.out.println(root.toUri());
        }
    }
}

您可以通过将解码的 URI 视为仍然是百分比编码来解决它:

parentURIToCheck = URI.create(
    parentURIToCheck.getScheme() + ":" +
    parentURIToCheck.getSchemeSpecificPart());
于 2015-07-03T00:39:10.120 回答