我目前正在开发一个创建 TCP 套接字并侦听服务器以获取传入 xml 的项目。xml 有时相当大,大约 1-3 mb。xml 不断来自套接字,我需要在它到来时对其进行解析。我尝试了许多解析器,例如 DomParser、XMLPullParser 和 SaxParser。萨克斯似乎是最快的,所以我继续这样做。但是现在我有时会遇到 OutOfMemory 异常。
我在这篇文章中读到,我们应该以块的形式向解析器提供数据。
如何在 Android 应用程序中解析来自 web 服务的大量 xml 数据?
有人可以告诉我这是怎么做到的。我当前的代码就像
InputSource xmlInputSource = new InputSource(new StringReader(response));
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = null;
XMLReader xr = null;
try{
sp = spf.newSAXParser();
xr = sp.getXMLReader();
ParseHandler xmlHandler = new ParseHandler(context.getSiteListArray().indexOf(website), context);
xr.setContentHandler(xmlHandler);
xr.parse(xmlInputSource);
postSuccessfullParsingNotification();
}catch(SAXException e){
e.printStackTrace();
}catch(ParserConfigurationException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
e.toString();
}
其中 response 是我从套接字接收到的字符串。
是否应该研究其他解析器,例如 VTD-XML?或者有没有办法让萨克斯有效地工作?
顺便说一句:每当一个新字符串到达要解析的套接字时,我都会打开一个新线程来解析字符串。
This is my handler code
public class ParseHandler extends DefaultHandler {
private Website mWebsite;
private Visitor mVisitor;
private VisitorInfo mVisitorInfo;
private boolean isVisit;
private boolean isVisitor;
private AppContext appContext;
public ParseHandler(int index,AppContext context){
appContext = context;
mWebsite = appContext.getSiteListArray().get(index);
}
@Override
public void startDocument() throws SAXException {
super.startDocument();
}
@Override
public void startElement(String namespaceURI, String localName,String qName, Attributes atts)
throws SAXException {
if(localName.equals("visit")) {
isVisit = true;
} else if(localName.equals("visitor") && isVisit) {
isVisitor = true;
mVisitor = new Visitor();
mVisitor.mDisplayName = "Visitor - #"+atts.getValue("id");
mVisitor.mVisitorId = atts.getValue("id");
mVisitor.mStatus = atts.getValue("idle");
} else if(localName.equals("info") && isVisitor){
mVisitorInfo = mVisitor.new VisitorInfo();
mVisitorInfo.mBrowser = atts.getValue("browser");
mVisitorInfo.mBrowserName = atts.getValue("browser").replace("+", " ");
mVisitorInfo.mCity = atts.getValue("city").replace("+", " ");
mVisitorInfo.mCountry = atts.getValue("country");
mVisitorInfo.mCountryName = atts.getValue("country");
mVisitorInfo.mDomain = atts.getValue("domain");
mVisitorInfo.mIp = atts.getValue("ip");
mVisitorInfo.mLanguage = atts.getValue("language");
mVisitorInfo.mLatitude = atts.getValue("lat");
mVisitorInfo.mLongitude = atts.getValue("long");
mVisitorInfo.mOrg = atts.getValue("org").replace("+", " ");
mVisitorInfo.mOs = atts.getValue("os");
mVisitorInfo.mOsName = atts.getValue("os").replace("+", " ");
mVisitorInfo.mRegion = atts.getValue("region").replace("+", " ");
mVisitorInfo.mScreen = atts.getValue("screen");
}
}
@Override
public void characters(char ch[], int start, int length) {
}
@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
if(localName.equals("visit")) {
isVisit = false;
} else if(localName.equals("visitor")) {
isVisitor = false;
if(mVisitor == null){
Log.e("mVisitor","mVisitor");
} else if(mVisitor.mVisitorId == null){
Log.e("mVisitor.mVisitorId","mVisitor.mVisitorId");
}
mWebsite.mVisitors.put(mVisitor.mVisitorId, mVisitor);
} else if(localName.equals("info") && isVisitor) {
mVisitor.mVisitorInfo = mVisitorInfo;
}
}
@Override
public void endDocument() throws SAXException {
}
}
**
编辑:经过思考..
**
经过进一步调查,我发现我的解析没有导致异常。每次我从套接字接收到一个流时,我都会将它存储在一个字符串中,并且我会一直附加它,直到我们在流中得到“\n”。"\n" 用于表示 xml 块的结束。该字符串导致内存异常。我尝试了StringBuilder但这也导致了同样的问题。我不知道为什么会这样。
现在我尝试直接发送输入流进行解析,但最后的“\n”会导致解析异常。我们可以设置什么让解析器忽略“\n”吗?