Я работаю на клиенте Android, который читает поток данных XML с моего сервера Java через сокет TCP.Сервер отправляет символ '\ n' в качестве разделителя между последовательными ответами.Ниже приведена модель реализации.
<response1>
<datas>
<data>
.....
.....
</data>
<data>
.....
.....
</data>
........
........
</datas>
</response1>\n <--- \n acts as delimiter ---/>
<response2>
<datas>
<data>
.....
.....
</data>
<data>
.....
.....
</data>
........
........
</datas>
</response2>\n
Хорошо, я надеюсь, что структура теперь ясна.Этот ответ передается с сервера, сжатого zlib.Поэтому я должен сначала надуть все, что я читаю с сервера, отдельно по ответу, используя разделитель и анализ.И Я использую SAX для анализа моего XML
Теперь моя главная проблема в том, что xml-ответ от сервера может быть очень большим (может быть в диапазоне от 3 до 4 МБ).Поэтому
для разделения ответов на основе разделителя (\ n) я должен использовать stringBuilder для хранения блоков ответов, так как он читает из сокета, а на некоторых телефонах StringBuilder не можетхранить строки в диапазоне MegaBytes.Это дает OutOfMemory исключение, и из таких потоков, как this Я узнал, что хранить большие строки (даже на временной основе) не очень хорошая идея.
Далее я попытался передать inflatorReadStream (который, в свою очередь, получает данные из входного потока сокетов) в качестве входного потока анализатора SAX (не пытаясь самостоятельно разделить xml и полагаясь на способность SAX найти конец документа на основепо тегам).На этот раз один ответ успешно анализируется, но затем при нахождении разделителя '\ n' SAX выбрасывает ExpatParserParseException , говоря мусор после элемента документа .
- После перехватачто ExpatParserParseException Я попытался прочитать снова, но после выдачи исключения SAX Parser закрывает поток, поэтому, когда я пытаюсь снова прочитать / проанализировать, он дает IOException , говорящий, что входной поток закрыт.
Ниже приведен фрагмент кода того, что я сделал (для ясности удалены все несвязанные блоки try catch).
private Socket clientSocket = null;
DataInputStream readStream = null;
DataOutputStream writeStream = null;
private StringBuilder incompleteResponse = null;
private AppContext context = null;
public boolean connectToHost(String ipAddress, int port,AppContext myContext){
context = myContext;
website = site;
InetAddress serverAddr = null;
serverAddr = InetAddress.getByName(website.mIpAddress);
clientSocket = new Socket(serverAddr, port);
//If connected create a read and write Stream objects..
readStream = new DataInputStream(new InflaterInputStream(clientSocket.getInputStream()));
writeStream = new DataOutputStream(clientSocket.getOutputStream());
Thread readThread = new Thread(){
@Override
public void run(){
ReadFromSocket();
}
};
readThread.start();
return true;
}
public void ReadFromSocket(){
while(true){
InputSource xmlInputSource = new InputSource(readStream);
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();
postSuccessfullParsingNotification();
}catch(ParserConfigurationException e){
e.printStackTrace();
postSocketDisconnectionBroadcast();
break;
}catch (IOException e){
postSocketDisconnectionBroadcast();
e.printStackTrace();
e.toString();
break;
}catch (Exception e){
postSocketDisconnectionBroadcast();
e.printStackTrace();
break;
}
}
}
А теперь мои вопросы
- Есть ли способ заставить SAX Parser игнорировать ненужные символы после ответа xml, а не генерировать исключение и закрывать поток ..
- Если нет, есть ли способ избежать ошибки нехватки памяти в stringBuilder.Честно говоря, я не исключаю положительного ответа на этот вопрос.Есть обходной путь?