android - 从套接字读取大块 xml 数据并即时解析

标签 android sockets stream saxparser inflate

我正在开发一个 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;
       }
    }
}

现在我的问题是

  1. 有没有办法让 SAX 解析器在 on 之后忽略垃圾字符 xml 响应,而不是抛出异常并关闭流..
  2. 如果没有,有什么办法可以避免内存不足错误 字符串生成器。坦白说,我不排除对这个问题给予肯定的回答 这。有什么解决办法吗?

最佳答案

  1. 您也许可以在读取器或流周围使用包装器,将其传递给检测换行符的过滤器,然后关闭解析器并启动一个继续处理流的新解析器:您的流不是有效的 XML,您将获胜无法像您当前实现的那样解析它。看看http://commons.apache.org/io/api-release/org/apache/commons/io/input/CloseShieldInputStream.html .
  2. 没有。

关于android - 从套接字读取大块 xml 数据并即时解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7074036/

相关文章:

java - AsyncTask已经完成

java - 为什么 instantiateItem 不调用,ViewPager 不工作?

android - 创建TCP套接字时无法识别Android主机名

.net - .NET 中的 RIO(注册 I/O)套接字

python - 如何使用 name 属性实例化 io.TextIOWrapper 对象?

c++ - 在什么情况下从流(的末尾)读取会导致停顿?

android - 如何从 OnPostExecute 中提取字符串到我的主 Activity

android - 新安装的 Eclipse 和 Android SDK。无法让模拟器工作。卡在时钟屏幕上

c++ - 连接失败后如何清理套接字?

java - Java中通过Socket进行文件传输,不会跳出while循环