org.xml.sax.SAXParseException: Premature end of file

當使用XML的schema去驗證XML文檔的時候曝出如題的錯誤,驗證代碼如下:

public static boolean validateXml(String xsd, InputStream input){
    boolean flag = true;
    SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema;
    try {
        Resource resource = new ClassPathResource(xsd);
        schema = factory.newSchema(resource.getURL());
        Validator validator = schema.newValidator();
        validator.validate(new StreamSource(input));
    } catch (SAXException | IOException e) {
        flag = false;
        logger.error("validate xml failed");
        e.printStackTrace();
    }
    return flag;
}

驗證的代碼如下:

InputStream input = new ClassPathResource("person.xml").getInputStream();
String xml = IOUtils.toString(input);
boolean flag = XmlUtils.validateXml("mapping.xsd", input);
System.out.println(flag);

當通過該方法去驗證時報出org.xml.sax.SAXParseException:Premature end of file錯誤,經過調試發現是InputStream的原因,即一個InputStream流對象只能執行一次讀取操作,當執行完讀取操作之後再次執行已經無法讀取出內容,這裏由於是將讀取一次的xml輸入流再經過xsd驗證,所以會報出如上的錯誤!

測試如下:

public void testInputStream() throws IOException {
    String test = "test inputStream";
    InputStream inputStream = new ByteArrayInputStream(test.getBytes());

    String str1 = IOUtils.toString(inputStream);
    System.out.println("first call : " + str1);

    String str2 = IOUtils.toString(inputStream);
    System.out.println("second call : " + str2);
}

執行結果如下:

1
這裏寫圖片描述

從上面可以看出當第二次查詢的時候輸入流中已經沒有數據了。如果想在第二次查詢的時候仍然能夠查出相同的內容,則需要使用reset()InputStream的指針移回到開始再進行讀取,如下:

public void testInputStream() throws IOException {
    String test = "test inputStream";
    InputStream inputStream = new ByteArrayInputStream(test.getBytes());

    String str1 = IOUtils.toString(inputStream);
    System.out.println("first call : " + str1);

    inputStream.reset();

    String str2 = IOUtils.toString(inputStream);
    System.out.println("second call : " + str2);
}

2
這裏寫圖片描述

可以看出已經能夠讀取和第一次相同的內容了!

從這個例子可以看出,其實InputStream就是一個字符序列,在讀取的時候內部通過一個指針來指向要讀取的數據,當讀取完畢後,指針指向尾部,繼續讀取的時候不會讀取新的數據,所以需要reset()將指針移動到開始,實際上reset()實際上是和mark()配合使用的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章