我调用了HashMap的containsKey方法,我期望返回true。如果我将程序编译为.class文件并运行它,它返回true,但如果我构建一个JAR,那么同样的调用返回false,原因是我无法理解。
我已经调试了.class和JAR版本(使用http://www.eclipsezone.com/eclipse/forums/t53459.html中描述的远程连接的JAR),在这两种情况下,HashMap似乎包含了我尝试的密钥检查。
HashMap使用URI对象作为键。以下是每个调试会话中显示的变量的内容:
以.class文件格式运行
HashMap Key: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格式运行
HashMap Key: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
。在JAR中,URI在某种程度上表现不同吗?发生了什么事?
提前感谢您的帮助!
修改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情况下,URI parentURIToCheck
是双重编码的(对于应该有%20的空格,%5250),而在.class情况下,这不会发生。知道为什么吗?
答案 0 :(得分:1)
这与HashMap无关。您似乎在Java Zip File System Provider中发现了一个错误,即它将Path转换为双重编码的URI。
我找不到它的现有错误,所以我提交了一个。 (有this related bug,我怀疑其修复的原因是这个。)更新:这是Java bug 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());