當使用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);
}
執行結果如下:
從上面可以看出當第二次查詢的時候輸入流中已經沒有數據了。如果想在第二次查詢的時候仍然能夠查出相同的內容,則需要使用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);
}
可以看出已經能夠讀取和第一次相同的內容了!
從這個例子可以看出,其實InputStream就是一個字符序列,在讀取的時候內部通過一個指針來指向要讀取的數據,當讀取完畢後,指針指向尾部,繼續讀取的時候不會讀取新的數據,所以需要reset()
將指針移動到開始,實際上reset()
實際上是和mark()
配合使用的。