验证并使用相同的输入流读取 [英] Validate AND read with the same inputstream

查看:101
本文介绍了验证并使用相同的输入流读取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Web服务,该服务从xml文件获取输入流.现在,我想验证并使用相同的输入流读取它.我使用mark并将其重置.

在Glassfish和Websphere上运行正常.但是,当我使用openEJB运行集成测试时,流将在验证后关闭.我可以在一个简单的例子中重现它.

我如何更好地实现它?验证程序实现始终相同.但是每种环境都使用输入流的另一种实现.

public class XMLReader {
public static void main(String[] args) {
    try {
        XMLReader reader = new XMLReader();
        InputStream stream = new BufferedInputStream(new FileInputStream(
                new File("myXML.xml")));
        reader.read(stream);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public void read(InputStream xmlInputStream) throws SAXException,
        IOException {
    if (xmlInputStream.markSupported()) {
        xmlInputStream.mark(0);
        validateXML(xmlInputStream);
        xmlInputStream.reset();
        readXML(xmlInputStream);
    }
}

private void readXML(InputStream xmlInputStream) {
    // READ xmInputStream with STAX, JAXB, etc. whatever

}

private void validateXML(InputStream xmlInputStream) throws SAXException,
        IOException {
    Source schemaFile = new StreamSource(new File("myXSD.xsd"));
    Source xmlFile = new StreamSource(xmlInputStream);
    SchemaFactory schemaFactory = SchemaFactory
            .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema = schemaFactory.newSchema(schemaFile);
    Validator validator = schema.newValidator();
    try {
        validator.validate(xmlFile);
        System.out.println("is valid");
    } catch (SAXException e) {
        System.out.println("is NOT valid");
        System.out.println("Reason: " + e.getLocalizedMessage());
    }
}
}

例外:

  java.io.IOException: Stream closed
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:145)
at java.io.BufferedInputStream.reset(BufferedInputStream.java:414)
at xmltest.XMLReader.read(XMLReader.java:36)
at xmltest.XMLReader.main(XMLReader.java:27)

解决方案

不幸的是,XML解析器在完成读取后就关闭了流.我不明白为什么这样做确实如此,并且我不建议任何人关闭他们不拥有的信息流.可能有一个原因让我无法快速掌握.

无论如何,您可以做的是拥有一个BufferedInputStream,它不会关闭包装好的InputSteam:

public static void main(String[] args) {
    try (FileInputStream in = new FileInputStream(new File("myXML.xml"))){
        XMLReader reader = new XMLReader();
        InputStream stream = new BufferedInputStream(in) {
            @Override
            public void close() throws IOException {
               // don't close
            }
        };
        reader.read(stream);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

i have a webservice which get an inputstream from a xml- file. Now, i want validate AND read it with the same inputstream. I use mark and reset for it.

On Glassfish and Websphere it works fine. But when i run my integration tests with openEJB, the stream will be closed after validation. I can reproduce it in a simple example.

How can i realize it better? The Validator Implementation is always the same. But every environment use another implementation of inputstream.

public class XMLReader {
public static void main(String[] args) {
    try {
        XMLReader reader = new XMLReader();
        InputStream stream = new BufferedInputStream(new FileInputStream(
                new File("myXML.xml")));
        reader.read(stream);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public void read(InputStream xmlInputStream) throws SAXException,
        IOException {
    if (xmlInputStream.markSupported()) {
        xmlInputStream.mark(0);
        validateXML(xmlInputStream);
        xmlInputStream.reset();
        readXML(xmlInputStream);
    }
}

private void readXML(InputStream xmlInputStream) {
    // READ xmInputStream with STAX, JAXB, etc. whatever

}

private void validateXML(InputStream xmlInputStream) throws SAXException,
        IOException {
    Source schemaFile = new StreamSource(new File("myXSD.xsd"));
    Source xmlFile = new StreamSource(xmlInputStream);
    SchemaFactory schemaFactory = SchemaFactory
            .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema = schemaFactory.newSchema(schemaFile);
    Validator validator = schema.newValidator();
    try {
        validator.validate(xmlFile);
        System.out.println("is valid");
    } catch (SAXException e) {
        System.out.println("is NOT valid");
        System.out.println("Reason: " + e.getLocalizedMessage());
    }
}
}

Exception:

  java.io.IOException: Stream closed
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:145)
at java.io.BufferedInputStream.reset(BufferedInputStream.java:414)
at xmltest.XMLReader.read(XMLReader.java:36)
at xmltest.XMLReader.main(XMLReader.java:27)

解决方案

Unfortunately, the XML parser closes the stream upon finishing reading. I don't understand why it does that really and I wouldn't recommend anyone to closing streams that they don't own. There might be a reason that I couldn't grasp that quickly.

Anyways, what you could do is having a BufferedInputStream, that does not close the wrapped InputSteam:

public static void main(String[] args) {
    try (FileInputStream in = new FileInputStream(new File("myXML.xml"))){
        XMLReader reader = new XMLReader();
        InputStream stream = new BufferedInputStream(in) {
            @Override
            public void close() throws IOException {
               // don't close
            }
        };
        reader.read(stream);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

这篇关于验证并使用相同的输入流读取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆