JAXB 无法加载名称包含 URL 编码字符的文件

JAXB fails to load file having name containing URL encoded characters

我有一个文件,其路径如下所示 /home/jwayne/test/55-0388%25car.xml。我尝试使用 JAXB 将 XML 解组回一个对象,如下所示。

File file = new File("/home/jwayne/test/55-0388%25car.xml");
JAXBContext context = JAXBContext.newInstance(Rectangle.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Rectangle rectangle = (Rectangle) unmarshaller.unmarshal(file);

但是,我得到一个 FileNotFoundException (FNFE),堆栈跟踪如下。

[java.io.FileNotFoundException: /home/jwayne/test/55-0388%car.xml (没有那个文件或目录)]
    在 com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:246)
    在 com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
    在 javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(摘要UnmarshallerImpl.java:157)
    在 javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(摘要UnmarshallerImpl.java:162)
    在 javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(摘要UnmarshallerImpl.java:171)
    在 javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(摘要UnmarshallerImpl.java:189)
...

请注意,以某种方式(如堆栈跟踪所建议的那样),解组器已将文件名从 55-0388%25car.xml 修改为 55-0388%car.xml

单步执行代码,但是,问题实际上很深:sun.net.www.protocol.file.Handler 有一个方法 openConnection 执行以下操作。

File var4 = new File(ParseUtil.decode(var1.getPath()));

那个sun.net.www.ParseUtil.decode方法实际上是转换了文件路径。

知道如何快速解决这个问题吗(除了重命名文件)? (注意我使用的是 JDK v1.8.0_191)。

您的问题的根本原因是有一个 % 用于 URL 编码特殊字符。 %%25.

JAXB 在内部所做的是将 %25 解码为纯 %,因此无法找到该文件。

快速(和肮脏的)解决方案是进行一些字符串替换,例如:

String fileName = "/home/jwayne/test/55-0388%25car.xml": 
fileName = fileName.replace("%25", "%2525");
File file = new File(fileName);

只要文件名中有 %25,这就适用。但我想这会发生在任何 URL 编码的字符上。因此,如果有任何其他特殊字符,您需要对每个或一些聪明的正则表达式解决方案进行一些处理。

更新:

要解决此 JAXB 行为,请为其提供 InputStream 而不是 File。所以喜欢:

FileInputStream fis = new FileInputStream(fileName);        
Rectangle r2 = (Rectangle) unmarshaller.unmarshal(fis);

那么 JAXB 就无法更改任何 URI/文件名。