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

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

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

    于吉吉的技術(shù)博客

    建造高性能門戶網(wǎng)

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

    1.使用Dom4j解析大文件時(shí)內(nèi)存溢出的問題

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

    常用的Dom4j文件解析方式:

    InputStream is = new FileInputStream(filePath);
    SAXReader reader 
    = new SAXReader();  //將整個(gè)XML構(gòu)建為一個(gè)Document
    Document doc = reader.read(is);
    Element root 
    = doc.getRootElement(); // 獲得根節(jié)點(diǎn)
    for (Object obj : root.elements()) { // 遍歷每個(gè)節(jié)點(diǎn)
    Element e = (Element)obj;            // 對(duì)當(dāng)前節(jié)點(diǎn)進(jìn)行操作
    }

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

    通過查API可以發(fā)現(xiàn)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.

    好了,它就是我們想要的,通過實(shí)現(xiàn)以下兩個(gè)method,就可以達(dá)成我們的需求

    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 的實(shí)例
    reader.addHandler("/root/test1", addHandler); // 節(jié)點(diǎn)
    reader.addHandler("/root/test2", addHandler); // 節(jié)點(diǎn)
    reader.read(fis);

    ...

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

    因?yàn)槊看翁幚硗暌粋€(gè)節(jié)點(diǎn)后并沒有保存在dom樹中,所以不會(huì)出現(xiàn)內(nèi)存溢出的情況
    上面的省略了一些業(yè)務(wù)代碼,不知道你是否明白或有更好的方法,可以和我聯(lián)系QQ:34174409

    2.BOM頭問題

    使用java.io.Reader讀取XML文件進(jìn)行解析時(shí)出現(xiàn)異常
    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類無法正確識(shí)別

    解決方法:
    (1).使用16進(jìn)制編輯器手動(dòng)刪除BOM頭

    這個(gè)...自行解決

    (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);
    //寫入臨時(shí)文件
    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();

    //臨時(shí)文件寫完,開始將臨時(shí)文件寫回本文件。
    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文件時(shí)出現(xiàn)非法字符的Exception(即使該字符位于CDATA段內(nèi)):    org.xml.sax.SAXParseException: An invalid XML character (Unicode: 0xb) was found in the CDATA section.
    原因在于:根據(jù)W3C標(biāo)準(zhǔn),有一些字符不能出現(xiàn)在XML文件中:
        0x00 - 0x08
        0x0b - 0x0c
        0x0e - 0x1f
    解析XML時(shí)遇到這些字符就會(huì)出錯(cuò)

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

    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) 評(píng)論(2)  編輯  收藏 所屬分類: xml 、java

    評(píng)論

    # re: 解析xml時(shí)遇到的一些問題 2010-09-29 07:35 何楊
    不錯(cuò)!  回復(fù)  更多評(píng)論
      

    # re: 解析xml時(shí)遇到的一些問題 2010-09-29 10:15 陳于喆
    @何楊
    謝謝,你的blog寫得很精彩,以后會(huì)抽時(shí)間去關(guān)注的  回復(fù)  更多評(píng)論
      


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 日本亚洲中午字幕乱码| 国产性生交xxxxx免费| 又硬又粗又长又爽免费看| 亚洲区视频在线观看| 亚洲日韩精品无码专区网址| 日本不卡高清中文字幕免费| 国产精品1024永久免费视频| a级男女仿爱免费视频| 欧洲美女大片免费播放器视频| 亚洲精品国产摄像头| 亚洲日韩在线视频| 亚洲AV无码成人精品区在线观看| 亚洲性日韩精品国产一区二区| 精品国产免费观看久久久| 永久免费av无码网站韩国毛片 | 日本特黄a级高清免费大片| 在线视频精品免费| 18未年禁止免费观看| 久久国产乱子伦精品免费看| 成人国产精品免费视频| 一级毛片aa高清免费观看| 精品在线免费视频| 国产亚洲视频在线观看网址| 亚洲Av无码国产一区二区| 亚洲国产成人手机在线观看| 亚洲AV男人的天堂在线观看| 亚洲一区二区无码偷拍| 亚洲国产日韩精品| 亚洲精品午夜国产va久久| 欧洲 亚洲 国产图片综合| 亚洲AV无码专区在线亚| 2017亚洲男人天堂一| 亚洲视频无码高清在线| 亚洲卡一卡二卡乱码新区| 亚洲狠狠色丁香婷婷综合| MM1313亚洲国产精品| 免费又黄又爽又猛大片午夜| fc2成年免费共享视频网站| 中文字幕永久免费视频| 毛片免费在线观看| 97在线视频免费公开观看|