<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    于吉吉的技術博客

    建造高性能門戶網

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      65 隨筆 :: 6 文章 :: 149 評論 :: 0 Trackbacks
    先感謝同事renial的<解析xml時遇到的一些問題>技術分享,下面是一些記錄和實際操作

    1.使用Dom4j解析大文件時內存溢出的問題

    問題是這樣的,當我用dom4j去解析一個幾十M的xml時,就出現out of memory.當然了,這也是根據你的機器性能而定的,我們都知道dom4j在各種DOM解析器中應該算是性能最好的,連大名鼎鼎的Hibernate都是用dom4j來解析XML配置文件的
    問題出在于使用dom4j的SAXReader是會把整個XML文件一次性讀入,如果XML文件過大就會拋出out of memory,但即使是使用SAXParser批量讀入解析,但它也是一次解析完,假設XML文件有幾萬條數據,那么解析后就必須在內存放入這幾萬條對象.

    常用的Dom4j文件解析方式:

    InputStream is = new FileInputStream(filePath);
    SAXReader reader 
    = new SAXReader();  //將整個XML構建為一個Document
    Document doc = reader.read(is);
    Element root 
    = doc.getRootElement(); // 獲得根節點
    for (Object obj : root.elements()) { // 遍歷每個節點
    Element e = (Element)obj;            // 對當前節點進行操作
    }

    解決方法:使用ElementHandler解析文件

    通過查API可以發現ElementHandler接口,下面是接口的介紹

    ElementHandler interface defines a handler of Element objects. It is used primarily in event based processing models such as for
    processing large XML documents as they are being parsed rather than waiting until the whole document is parsed.

    好了,它就是我們想要的,通過實現以下兩個method,就可以達成我們的需求

    onEnd(ElementPath elementPath)
              Called by an event based processor when an elements closing tag is encountered.
    onStart(ElementPath elementPath)
              Called by an event based processor when an elements openning tag is encountered.

    下面是代碼

    FileInputStream fis = new FileInputStream(addPath);
    SAXReader reader 
    = new SAXReader();
    ElementHandler addHandler 
    = new MyElementHandler();  //建立 MyElementHandler 的實例
    reader.addHandler("/root/test1", addHandler); // 節點
    reader.addHandler("/root/test2", addHandler); // 節點
    reader.read(fis);

    ...

    class MyElementHandler implements ElementHandler {
      
    public void onStart(ElementPath ep) {}
      
      
    public void onEnd(ElementPath ep) {
        Element e 
    = ep.getCurrent(); // 獲得當前節點
        
    // 對節點進行操作。。。
        e.detach(); // 處理完當前節點后,將其從dom樹中剪除
      }
    }

    因為每次處理完一個節點后并沒有保存在dom樹中,所以不會出現內存溢出的情況
    上面的省略了一些業務代碼,不知道你是否明白或有更好的方法,可以和我聯系QQ:34174409

    2.BOM頭問題

    使用java.io.Reader讀取XML文件進行解析時出現異常
    org.dom4j.DocumentException: Error on line 1 of document : Content is not allowed in prolog.
    Nested exception:
    org.xml.sax.SAXParseException: Content is not allowed in prolog.
    原因在于:UTF-8編碼文件存在BOM頭,Reader類無法正確識別

    解決方法:
    (1).使用16進制編輯器手動刪除BOM頭

    這個...自行解決

    (2).InputStream讀取流中前面的字符,看是否有BOM,如果有BOM,干掉BOM頭

    PushbackInputStream pis = new PushbackInputStream(in);
    int ch = pis.read();
    if (ch != 0xEF){
         testin.unread(ch);
    else if ((ch = pis.read()) != 0xBB){
         pis.unread(ch);
         pis.unread(
    0xef);
    else if ((ch = pis.read()) != 0xBF){
         
    throw new IOException("wrong format");
    else
    {
    }

    (3).InputStream讀取完文件,干掉BOM頭

    FileInputStream fin = new FileInputStream(fileName);
    //寫入臨時文件
    InputStream in = getInputStream(fin);
    String tmpFileName 
    = fileName + ".tmp";
    FileOutputStream out 
    = new FileOutputStream(tmpFileName);
    byte b[] = new byte[4096];

    int len = 0;
    while (in.available() > 0){
         len 
    = in.read(b, 04096);
         out.write(b, 
    0, len);
    }
    in.close();
    fin.close();
    out.close();

    //臨時文件寫完,開始將臨時文件寫回本文件。
    in = new FileInputStream(tmpFileName);
    System.out.println(
    "[" + fileName + "]");
    out 
    = new FileOutputStream(fileName);

    while (in.available() > 0){
         len 
    = in.read(b, 04096);
         out.write(b, 
    0, len);
    }
    in.close();
    out.close();

    (3).非法XML字符串

    解析XML文件時出現非法字符的Exception(即使該字符位于CDATA段內):    org.xml.sax.SAXParseException: An invalid XML character (Unicode: 0xb) was found in the CDATA section.
    原因在于:根據W3C標準,有一些字符不能出現在XML文件中:
        0x00 - 0x08
        0x0b - 0x0c
        0x0e - 0x1f
    解析XML時遇到這些字符就會出錯

    解決方法:
    對有可能出問題的XML文件,進行字符過濾后再進行解析。

    public static String stripNonValidXMLChars(String str) {
      
    if (str == null || "".equals(str)) {
        
    return str;
      }
      
    return str.replaceAll("[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]""");
    }


    ----------------------------------------

    by 陳于喆
    QQ:34174409
    Mail: chenyz@corp.netease.com


    posted on 2010-09-28 17:10 陳于喆 閱讀(15021) 評論(2)  編輯  收藏 所屬分類: xmljava

    評論

    # re: 解析xml時遇到的一些問題 2010-09-29 07:35 何楊
    不錯!  回復  更多評論
      

    # re: 解析xml時遇到的一些問題 2010-09-29 10:15 陳于喆
    @何楊
    謝謝,你的blog寫得很精彩,以后會抽時間去關注的  回復  更多評論
      


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 中文在线免费看视频| 8x8x华人永久免费视频| 亚洲AV无码成人精品区蜜桃| 999任你躁在线精品免费不卡| 亚洲 暴爽 AV人人爽日日碰| 亚洲国产精品毛片av不卡在线| 国产午夜精品久久久久免费视| 亚洲性线免费观看视频成熟| 亚洲日韩人妻第一页| h视频在线观看免费完整版| 久久精品国产亚洲AV天海翼| 亚洲国产第一站精品蜜芽| 在线观看免费毛片| 你好老叔电影观看免费| 亚洲AV日韩综合一区| 亚洲av无码专区在线播放 | 黄页网站在线观看免费高清| 一区二区三区免费在线视频 | 国产成人精品日本亚洲专| 亚洲一区二区三区无码影院| 免费专区丝袜脚调教视频| 一本久久A久久免费精品不卡| 亚洲国产成人精品青青草原| 亚洲熟女少妇一区二区| 成**人免费一级毛片| 91福利免费视频| 国产免费久久精品99久久| 亚洲精品中文字幕| 亚洲美女大bbbbbbbbb| 精品亚洲永久免费精品| 国产jizzjizz视频免费看| 亚洲高清中文字幕免费| 免费看搞黄视频网站| 黄色免费网址在线观看| 久久精品国产亚洲AV忘忧草18| 亚洲AV无码第一区二区三区| 亚洲国产综合无码一区二区二三区| 我要看WWW免费看插插视频| 3d成人免费动漫在线观看| 两个人看的www高清免费视频| 国产综合激情在线亚洲第一页|