提问人:Broshet 提问时间:11/2/2023 更新时间:11/2/2023 访问量:40
从 XSD 解组 XML 失败,JAR 执行时显示“java.io.IOException:缓冲区已关闭”
Unmarshal XML from XSD failed with JAR Execution with "java.io.IOException: Buffer already closed"
问:
我有一个 java 代码,可以从 PDF (Apache PDFBox) 中提取 Xml 部分并将其解组到 java 类中。
在使用 IntelliJ 进行本地执行时,一切正常,但是当我在 openshift 集群上部署 jar 时,unmarshal 是 ko with “java.io.IOException: Buffer already closed”
从我的 PDF 中提取了一个列表
然后,我创建一个像这样的 unmarshal:
try {
JAXBContext context = JAXBContext.newInstance(typeClasse.getClass());
Unmarshaller unmarshaller = context.createUnmarshaller();
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
String xsdFilePath = getXSD();
Schema schema = factory.newSchema(this.getClass().getResource("/" + xsdFilePath));
unmarshaller.setSchema(schema);
unmarshaller.setEventHandler(event -> false);
return unmarshaller;
} catch (JAXBException | SAXException e) {
throw new UnmarshallException(e);
}
typeClasse 是我的输出 unmarshall 类,getXSD() 为我提供根 XSD 定义的路径,我所有的 XSD 都在资源 java 文件夹上的同一目录“xsd”上,getXSD() 返回的一个包含所有其他。路径类似于“xsd/myparentXSD.xsd”
然后,使用我的 List (myList) 执行此代码,返回一个 List,其中 T 是 typeClasse。
myList.stream()
.map(myObject -> unmarshallFichier(myObject, unmarshaller))
.collect(Collectors.toList());
unmarshaller 是下面的一个细节,unmarshallFichier 是:
try {
StreamSource stream = new StreamSource(myObject);
JAXBElement<?> jaxbElement = unmarshaller.unmarshal(stream, typeClasse.getClass());
return (T) jaxbElement.getValue();
} catch (JAXBException e) {
throw new UnmarshallException(e);
}
但是在 openshift 上,这段代码是错误的,并产生 java.io.IOException: Buffer already closed (but not inc local)
这是怎么回事?
答:
StreamSource stream = new StreamSource(myObject);
在这种情况下是什么?是 InputStream 还是 Reader?myObject
从例外情况来看,我感觉您正在尝试从一个或多个次中阅读。Reader
InputStream
请注意,您只能从 InputStream
/ Reader
读取一次。
也许您想执行以下操作,以便在每次迭代列表时创建一个新列表?InputStream
public interface InputStreamSource {
InputStream get() throws IOException;
}
public class MyClass {
// myList is a long-lived object and can be iterated multiple times
// since we create a new InputStream each time we call InputStreamSource.get()
private final List<InputStreamSource> myList = List.of(
() -> new FileInputStream("path/to/file1.xml"),
() -> new FileInputStream("path/to/file2.xml")
);
public List<Object> doIt() {
return myList.stream()
.map(myObject -> unmarshallFichier(myObject, unmarshaller))
.collect(Collectors.toList());
}
private Object unmarshallFichier(InputStreamSource streamSource, Unmarshaller unmarshaller) {
try (InputStream in = streamSource.get()) {
StreamSource stream = new StreamSource(in);
JAXBElement<?> jaxbElement = unmarshaller.unmarshal(stream, typeClasse.getClass());
return (T) jaxbElement.getValue();
} catch (JAXBException e) {
throw new UnmarshallException(e);
}
}
}
评论
List<InputStream>
如果要多次迭代列表,则会出现问题。每个只能从一次读取。在你读完之后,它应该被丢弃,因为它在这一点上是无用的InputStream
InputStream
InputStream
InputStream
评论