В настоящее время я работаю над проектом, который создает сокет TCP и прослушивает сервер для получения входящего XML. Время от времени xml довольно большой, и его размер составит 1-3 мегабайта. XML продолжает поступать из сокета, и мне нужно разобрать его, как он приходит.
Я опробовал много парсеров, таких как DomParser, XMLPullParser и SaxParser. Сакс, казалось, был самым быстрым, поэтому я продолжил. Но теперь я иногда получаю исключение OutOfMemory.
Я прочитал в этом посте, что мы должны передавать данные парсеру кусками.
Как анализировать огромные XML-данные из веб-сервиса в приложении Android?
Может кто-нибудь сказать мне, как это делается. Мой текущий код похож на
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();
}
Где ответ - строка, которую я получаю из сокета.
Стоит ли смотреть на другие парсеры, такие как VTD-XML? Или есть способ заставить Sax работать эффективно?
Кстати: всякий раз, когда новая строка поступает в анализируемый сокет, я открываю новый поток для анализа строки.
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"?