我正在开发一个 android 客户端,它通过 TCP 套接字从我的 java 服务器读取连续的 xml 数据流。服务器发送“\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 MB 的范围内)。所以
要根据分隔符 (\n) 分隔响应,我必须使用 stringBuilder 在从套接字读取时存储响应 block 在某些手机上 StringBuilder 无法将字符串存储在 兆字节范围。它给出了 OutOfMemory 异常,并且来自 类似 this 的线程我开始知道保持大字符串(即使在 临时基础)不是一个好主意。
接下来我尝试传递 inflatorReadStream (它又获取数据 来自套接字输入流)作为SAX解析器的输入流(不带 自己费心去分离xml,依靠SAX的能力来查找 基于标签的文档结尾)。这次得到一个回应 解析成功,但随后找到 '\n' 分隔符 SAX 抛出 ExpatParserParseException 并在文档后说 垃圾 元素 .
- 捕获 ExpatParserParseException 后,我尝试阅读 再次,但抛出异常后 SAX 解析器关闭流,所以 当我尝试再次读取/解析时,它给出 IOException 说 输入流已关闭。
下面给出了我所做的代码 fragment (为了清楚起见,删除了所有不相关的 try catch block )。
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 解析器在 on 之后忽略垃圾字符 xml 响应,而不是抛出异常并关闭流..
- 如果没有,有什么办法可以避免内存不足错误 字符串生成器。坦白说,我不排除对这个问题给予肯定的回答 这。有什么解决办法吗?
最佳答案
- 您也许可以在读取器或流周围使用包装器,将其传递给检测换行符的过滤器,然后关闭解析器并启动一个继续处理流的新解析器:您的流不是有效的 XML,您将获胜无法像您当前实现的那样解析它。看看http://commons.apache.org/io/api-release/org/apache/commons/io/input/CloseShieldInputStream.html .
- 没有。
关于android - 从套接字读取大块 xml 数据并即时解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7074036/