Android SaxParser и исключение OutOfMemory - PullRequest
2 голосов
/ 13 августа 2011

В настоящее время я работаю над проектом, который создает сокет 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"?

Ответы [ 2 ]

0 голосов
/ 16 августа 2011

Еще одна публикация была сделана на SO с моей проблемой, и ответом были решения моей проблемы.

Вот решения для тех, кто имеет эту проблему.

Чтение большого объема XML-данных из сокета и анализ на лету

0 голосов
/ 13 августа 2011

кажется, что вы передаете весь xml-файл парсеру, поэтому всякий раз, когда файл слишком велик, вы получаете исключение outOfMemory.

Вы должны попытаться прочитать выходные данные из сокета порциямискормить его парсеру как он придет.Так что вы бы сделали xr.parse () внутри цикла.

...