我正在开发一个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)我必须使用a stringBuilder 用于存储从套接字读取的响应块 而在某些手机上StringBuilder无法存储字符串 MegaBytes系列。它提供 OutOfMemory 例外,并且来自 像this这样的线程我知道保持大字符串(即使是在 临时基础)不是一个好主意。
接下来我尝试传递inflatorReadStream(后者又传递数据) 来自套接字输入流)作为SAX解析器的输入流(没有 打扰自己分离xml并依赖SAX的查找能力 基于标签的文档结尾)。这一次得到一个回应 解析成功,但后来找到'\ n'分隔符SAX 抛出 ExpatParserParseException 在文档后面说垃圾 元素。
下面给出了我所做的代码片段(为清楚起见,删除了所有不相关的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;
}
}
}
现在我的问题是
答案 0 :(得分:2)
答案 1 :(得分:1)
如果您的SAX解析器支持推送模型(您自己将原始数据块推入其中并在解析原始数据时触发事件),那么您可以在SAX会话开始时简单地推送您自己的初始XML标记。这将成为顶级文档标记,然后您可以在收到响应时推送响应,就SAX而言,它们将是二级标记。这样,您可以在同一个SAX会话中推送多个响应,然后在OnTagOpen事件中(或者您正在使用的那个),当您在级别1检测到其标记名称时,您将知道何时开始新的响应。