6

我正在使用以下代码在 Windows 7 x64 上使用带有 Java 1.7.0_03 的 JAXB 解组 XML 文件:

 try (InputStream xsdStream = ConfigurationService.class.getClassLoader().getResourceAsStream(CONFIG_XSD_FILE_NAME)) {
            configFile = new File(configFilePath);
            if (configFile.exists()) {
                context = JAXBContext.newInstance(Config.class);
                Unmarshaller unMarshaller = context.createUnmarshaller();

                SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
                StreamSource xsdStreamSource = new StreamSource(xsdStream);
                Schema schema = sf.newSchema(xsdStreamSource);

                unMarshaller.setSchema(schema);
                Object xmlObject = Config.class.cast(unMarshaller.unmarshal(configFile));
                myConfig = (Config) xmlObject;
            } else {
                log.severe(configFile.getAbsolutePath() + " does not exist, can not parse configuration info from it.");
            }
  }

调用此方法的代码随后会删除 XML 文件。

如果解组成功,XML 文件将正确删除。但是,如果上面的代码抛出异常,例如。SAXException,XML 文件无限期保持锁定,调用代码无法使用 File.delete() 将其删除。

在这种情况下,这感觉就像 JAXB 没有关闭资源/文件。以某种方式这样做是我的责任还是这是一个错误?

审查 Unmarshaller 的javadoc并没有对此有所了解,谷歌搜索这个问题揭示了这个 2008 年的老问题

4

2 回答 2

8

简短的回答

您描述的行为听起来像是 JAXB 参考实现中的错误。您可以使用以下链接开票:

解决问题

File您可以从 a 解组FileInputStream并控制它在解组后自己正确关闭,而不是从 a解组。


长答案

我无法重现您所看到的问题。我在下面包含了我尝试过的内容。我在 Mac 上使用 JDK 1.7.0_07 x64。

配置服务

下面的大部分代码都是从您的问题中复制而来的。我添加了删除输入文件的调用,如果文件仍然存在则输出。

package forum14765898;

import java.io.*;

import javax.xml.XMLConstants;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;

public class ConfigurationService {

    private static final String CONFIG_XSD_FILE_NAME = "forum14765898/schema.xsd";

    public static void main(String[] args) throws Exception {
        File configFile = null;
        String configFilePath = "src/forum14765898/input.xml";
        JAXBContext context;
        Config myConfig;

        try (InputStream xsdStream = ConfigurationService.class.getClassLoader().getResourceAsStream(CONFIG_XSD_FILE_NAME)) {
            configFile = new File(configFilePath);
            if (configFile.exists()) {
                context = JAXBContext.newInstance(Config.class);
                Unmarshaller unMarshaller = context.createUnmarshaller();

                SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
                StreamSource xsdStreamSource = new StreamSource(xsdStream);
                Schema schema = sf.newSchema(xsdStreamSource);

                unMarshaller.setSchema(schema);
                Object xmlObject = Config.class.cast(unMarshaller.unmarshal(configFile));
                myConfig = (Config) xmlObject;
            } else {
                //log.severe(configFile.getAbsolutePath() + " does not exist, can not parse configuration info from it.");
            }
        } catch(Exception e) {
            e.printStackTrace(System.out);
        }

        configFile.delete();
        System.out.println(configFile.exists());

    }

}

架构.xsd

下面是我正在使用的简单 XML 模式。

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
    <element name="config">
        <complexType>
            <sequence>
                <element name="bar" type="int"/>
            </sequence>
        </complexType>
    </element>
</schema>

输入.xml

下面是 XML 输入。根据 XML 模式,该bar元素无效。当Schema在此文档上设置a 时,Unmarshaller将足以导致Exception在执行解组操作时抛出 an。

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <bar>INVALID</bar>
</config>

配置

package forum14765898;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Config {

    public int bar;

}

输出

下面是运行演示代码的输出。它显示了验证异常,在最后一行我们看到 XML 文件已被成功删除,因为它不再存在。

javax.xml.bind.UnmarshalException
 - with linked exception:
[org.xml.sax.SAXParseException; systemId: file:/Users/bdoughan/Scratch/src/forum14765898/input.xml; lineNumber: 3; columnNumber: 23; cvc-datatype-valid.1.2.1: 'INVALID' is not a valid value for 'integer'.]
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:512)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:209)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:175)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189)
    at forum14765898.ConfigurationService.main(ConfigurationService.java:31)
Caused by: org.xml.sax.SAXParseException; systemId: file:/Users/bdoughan/Scratch/src/forum14765898/input.xml; lineNumber: 3; columnNumber: 23; cvc-datatype-valid.1.2.1: 'INVALID' is not a valid value for 'integer'.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:453)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3232)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(XMLSchemaValidator.java:3147)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(XMLSchemaValidator.java:3057)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2135)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:854)
    at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.endElement(ValidatorHandlerImpl.java:579)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.endElement(ValidatingUnmarshaller.java:91)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.endElement(SAXConnector.java:143)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:606)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1742)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2900)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:489)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:203)
    ... 6 more
false
于 2013-02-08T11:12:19.400 回答
0
    public CashCountCompleted CashDeposit(String path) throws Exception {
      // TODO Auto-generated method stub
      CashCountCompleted cashCountCompleted = null;
      File file = null;
      FileInputStream inputStram = null;
      try {
            file = new File(path);
      inputStram = new FileInputStream(file);
      JAXBContext jaxbContext = JAXBContext.newInstance(CashCountCompleted.class);
      Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
      cashCountCompleted = (CashCountCompleted) jaxbUnmarshaller.unmarshal(inputStram);         
      }catch (JAXBException e) {
          //throw new...        
      } catch (FileNotFoundException e) {
           //throw new...
      }finally{         
            try{
                if(inputStram !=null){
                    inputStram.close();
                }
            }catch(Exception exception){
               //throw new...
            }                 
      }
      return cashCountCompleted;    
}
于 2018-06-04T11:55:56.310 回答