用java 把数据库里的数据写入到xml, 数据量很大的 主表大概有3000W条数据。
在网上找了一些资料, 有 jdom, sax, dom4j, dom 等技术。
有人说dom4j好用,我就拿dom4j来写了简单的程序。
往xml里写入到20000多一点的数据,java.lang.OutOfMemoryError 错误。麻烦以前做过这方面工作的高手可以指点指点我这个菜鸟。求大家帮帮忙了。不一定要用dom4j的 只要能做出来就可以了。先谢谢大家了。

解决方案 »

  1.   

    3000W
    还是用SAX吧,分段编译,不会有java.lang.OutOfMemoryError 错误
      

  2.   

    有人写过一个,源码可供参考下
    package ctais.business.jczc.yhs.wfwzxxcx; import org.xml.sax.Attributes; 
    import org.xml.sax.SAXException; 
    import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; 
    import javax.xml.parsers.SAXParserFactory; 
    import java.io.Serializable; 
    import java.sql.Connection; 
    import java.sql.DriverManager; 
    import java.sql.SQLException; 
    import java.sql.Statement; 
    import java.util.ArrayList; 
    import java.util.HashMap; 
    import java.util.List; /** 
    * Title: SAX 方式解析 XML 文件 
    * Description:解决大文件报OutOfMemory的问题 
    * Company: **** 
    * @author: Pagecn 
    * @date: YYYY-MM-DD 
    */ 
    public class SAXApp extends DefaultHandler implements Serializable { 
        private String LableName = "";  // 节点名称 
        private String LableValue = ""; // 节点值 
        private HashMap hm = new HashMap();    // 临时保存数据 
        private List list = new ArrayList();    // 保存插入的SQL语句 
        /** 
        * 根据文件路径建立 SAX解析器 
        * @param uri 
        */ 
        public void parseURI(String uri) { 
            try { 
                SAXParserFactory spf = SAXParserFactory.newInstance(); 
                SAXParser sp = spf.newSAXParser(); 
                sp.parse(uri, this); 
            } catch (Exception e) { 
                e.printStackTrace(); 
            } 
        }     /** 
        * 开始遍历 
        * @throws SAXException 
        */ 
        public void startDocument() throws SAXException { 
            //System.out.println(" <?xml version=\"1.0\" encoding=\"GB2312\"?>"); 
        }     /** 
        * 取开始节点名称 
        * @param namespaceURI 
        * @param localName 
        * @param rawName 
        * @param attrs 
        * @throws SAXException 
        */ 
        public void startElement(String namespaceURI, String localName, String rawName, Attributes attrs) throws SAXException { 
            LableName = rawName; 
        }     /** 
        * 取节点值 
        * @param ch 
        * @param start 
        * @param length 
        * @throws SAXException 
        */ 
        public void characters(char ch[], int start, int length) throws SAXException {         // 过滤回车LableValue.indexOf("\n") == -1 
            if (LableValue.indexOf("\n") != -1) { 
                LableValue = ""; 
            } 
            // 处理节点值过长,出现分段读取的情况 
            if (LableName.equals("COL1") || LableName.equals("COL2") || LableName.equals("COL3")) { 
                LableValue += new String(ch, start, length); 
                LableValue.trim(); 
            } else { 
                LableValue = new String(ch, start, length); 
            } 
        }     /** 
        * 取结束节点名称 
        * @param namespaceURI 
        * @param localName 
        * @param rawName 
        * @throws SAXException 
        */ 
        public void endElement(String namespaceURI, String localName, String rawName) throws SAXException { 
            try { 
                // 获得有用节点信息放入HashMap 
                if (!(rawName.equals("XX") || rawName.equals("ITEM"))) { 
                    hm.put(rawName, LableValue.trim()); 
                    LableValue = ""; 
                } 
                // 组装SQL 
                if (rawName.equals("ITEM")) { 
                    list.add("INSERT INTO TAB_NAME (COL1,COL2,COL3)" 
                            + " VALUES(" 
                            + "'" + hm.get("COL1") + "'," 
                            + "'" + hm.get("COL2") + "'," 
                            + "'" + hm.get("COL3") + "')"); 
                    hm.clear(); 
                } 
            } catch (Exception e) { 
                e.getMessage(); 
            }     }     /** 
        * 遍历结束 
        * @throws SAXException 
        */ 
        public void endDocument() throws SAXException { 
            Statement stmt = null; 
            Connection conn = null; 
            int initsize = 0; 
            int size = 100; 
            try { 
                // 获取数据库连接 
                Class.forName("oracle.jdbc.driver.OracleDriver"); 
                conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:SID", "USER", "PASSWORD"); 
                stmt = conn.createStatement(); 
                initsize = stmt.getFetchSize(); 
                stmt.setFetchSize(size);             // 批量插入数据,提高存储效率 
                for (int i = 0; i < list.size(); i++) { 
                    stmt.addBatch((String) list.get(i)); 
                } 
                stmt.executeBatch();             // 关闭数据库句柄 
                stmt.setFetchSize(initsize); 
                stmt.close(); 
                conn.close(); 
            } catch (Exception e) { 
                e.printStackTrace(); 
                try { 
                    if (stmt != null) { 
                        if (initsize != 0) { 
                            stmt.setFetchSize(initsize); 
                        } 
                        stmt.close(); 
                    } 
                    if (conn != null) { 
                        conn.close(); 
                    } 
                } catch (SQLException ee) { 
                    ee.printStackTrace(); 
                } 
            } 
        }     /** 
        * 测试方法 
        * 处理过>100M的XML文件,顺利完成,不过这种方式比较适合格式比较整齐、单一的XML文件 
        */ 
        public static void main(String args[]) { 
    /* 
    <ROOT> 
            <XX> 
            <ITEM> 
              <COL1/> 
              <COL2/> 
              <COL3/> 
                </ITEM> 
            </XX> 
        </ROOT> 
    */ 
            SAXApp st = new SAXApp(); 
            st.parseURI("C:\\test.xml"); 
            st.parseURI("C:\\ykk2007.xml"); 
        } 
    }
      

  3.   

    这位大哥,上一段代码是把xml里的数据写入到数据库里的代码吧?
    你那里还有没有把数据库里的数据导入到xml里的代码段啊?
      

  4.   

    以文件形式一条一条的写不要生成dom树。
      

  5.   

    以文件形式一条一条的写不要生成dom树。
      

  6.   

    只要是按照流的方式读取XML就不会出现内存溢出的问题,java中好像SAX是这样实现的吧,这对大数量处理是比较好的!
      

  7.   

    额,我也从数据库中到处过大量数据到xml,我是以一百条数据为单位往下xml中写,采用dom4j,大约4100万,为出现溢出,可以试试。也可以用普通写文件的方法写成xml格式,多大数据都可搞定。
      

  8.   

    可以这样啊:读数据按分页的方式读取,先把一部分数据,生成文件xml,以后分批处理,没处理完一部分释放下内存
      

  9.   

    记录 datas [3000万]File xmlFile;OutputStream xmlOut = new FileOutputStream(xmlFile);xmlOut.write(root开始tag);for(data:datas){
       Document doc = dom4j jdom把一条记录data转化为dom结构
        byte docBytes[] = 将doc结构转化为byte[]
        xmlOut.write(docBytes);
        xmlOut.write(换行);
    }xmlOut.write(root开始tag);
      

  10.   


    自己也可以自己封装dom结构,并转化为byte。
      

  11.   

    要先搞清楚你为什么会出现outmemory 是因为你对字符串操作的太多了,你最好是利用多线程+批处理的形式,即每个线程处理100-1000条数据,然后起那么两三个线程,去并发处理,处理完毕后,将处理的总数目返回,作为下次处理的起始位置,然后依次去做,这样的话,应该不会出现内存溢出了。