我正在尝试通过套接字连接到一个远程服务器,我从套接字返回大的xml响应,由'\ n'字符分隔。
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<data>
.......
.......
</data>
</Response>\n <---- \n acts as delimiter
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<data>
....
....
</data>
</Response>\n
..
我正在尝试使用SAX Parser解析这些xml。理想情况下,我希望通过搜索'\ n'来获得对字符串的完整响应,并将此响应提供给解析器。但是因为我的单个响应非常大,所以当在字符串中保存如此大的xml时,我得到outOfMemory Exception。因此唯一的选择是将xml流式传输到SAX。
SAXParserFactory spfactory = SAXParserFactory.newInstance();
SAXParser saxParser = spfactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setContentHandler(new MyDefaultHandler(context));
InputSource xmlInputSource = new InputSource(new
CloseShieldInputStream(mySocket.getInputStream()));
xmlReader.parse(xmlInputSource);
我正在使用closeShieldInputStream来阻止SAX因为'\ n'而在异常时关闭我的套接字流。我问了previous question那个......
现在有时我会得到解析错误
org.apache.harmony.xml.ExpatParser$ParseException: At line 1, column 8: not well-formed (invalid token)
我搜索了它并且found通常在实际xml的编码与SAX期望的编码不同时出现此错误。我写了一个C程序并打印出xml,我的所有xml都是用UTF-8编码的。
现在我的问题..
OutputStream log = new BufferedOutputStream(new FileOutputStream("log.txt"));
InputSource xmlInputSource = new InputSource(new CloseShieldInputStream(new
TeeInputStream(mReadStream, log)));
xmlReader.parse(xmlInputSource);
我挂载SD卡时创建了一个名为log.txt的新文件,但它是空的......我用这个吗?
我用TeeInputStream本身进行了解决。感谢Hemal Pandya建议......
//open a log file in append mode..
OutputStream log = new BufferedOutputStream(new FileOutputStream("log.txt",true));
InputSource xmlInputSource = new InputSource(new CloseShieldInputStream(new
TeeInputStream(mReadStream, log)));
try{
xmlReader.parse(xmlInputSource);
//flush content in the log stream to file..this code only executes if parsing completed successfully
log.flush();
}catch(SaxException e){
//we want to get the log even if parsing failed..So we are making sure we get the log in either case..
log.flush();
}
答案 0 :(得分:1)
有没有办法打印(或写入任何文件)SAX的输入为 它从套接字流?
Apache Commons有一个TeeInputStream应该是有用的。
OutputStream log = new BufferedOutputStream(new FileOutputtStream("response.xml"));
InputSource xmlInputSource = new InputSource(new
CloseShieldInputStream(new TeeInputStream(mySocket.getInputStream(), log)));
我没有使用它,你可能想在独立程序中首先尝试找出close
语义,虽然查看文档和你的要求看起来你想要在结束时单独关闭它
答案 1 :(得分:0)
我对Expat并不熟悉,但为了实现您的目的,一般来说,您需要一个SAX解析器,它支持将数据推送到解析器,而不是让解析器从源中提取数据。检查Expat是否支持推送模型。如果是这样,那么你可以简单地从套接字中读取一大块数据,将其推送到解析器,它将从chuck中解析任何数据,缓存剩余的数据以便在下一次推送时使用。根据需要重复,直到准备好关闭套接字连接。在此模型中,\n
分隔符将被视为节点之间的杂项空格,因此您必须使用SAX事件来检测新<Response>
节点何时打开和关闭。此外,因为您在数据中接收多个<Response>
节点,并且XML不允许超过1个顶级文档节点,所以在开始推送套接字之前,需要将自定义开始标记推送到解析器中数据进入解析器。然后,自定义开始标记将成为顶级文档节点,<Response>
节点将成为它的子节点。