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/文件名。
我有一个文件,其路径如下所示 /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/文件名。