如何将大量数据从数据库存储到XML(内存问题)?

时间:2010-05-24 07:01:02

标签: java oracle

首先,我从数据库获取数据时出现问题,占用了太多内存并且失败了。我已经设置-Xmx1500M并且我正在使用滚动ResultSet以便处理。现在我需要从数据中创建一个XML,但我不能把它放在一个文件中。目前,我这样做:

while(rs.next()){
                i++;
                xmlStringBuilder.append("\n\t<row>");
                xmlStringBuilder.append("\n\t\t<ID>" + Util.transformToHTML(rs.getInt("id")) + "</ID>");
                xmlStringBuilder.append("\n\t\t<JED_ID>" + Util.transformToHTML(rs.getInt("jed_id")) + "</JED_ID>");
                xmlStringBuilder.append("\n\t\t<IME_PJ>" + Util.transformToHTML(rs.getString("ime_pj")) + "</IME_PJ>");
//etc.
                xmlStringBuilder.append("\n\t</row>");
                if (i%100000 == 0){
                                    //stores the data to a file with the name i.xml
                    storeKBR(xmlStringBuilder.toString(),i);
                    xmlStringBuilder= null;
                    xmlStringBuilder= new StringBuilder();  
                }

它有效;我得到12个100 MB的文件。现在,我想要做的是将所有数据放在一个文件中(我然后压缩),但如果只删除if部分,我就会耗尽内存。我想过尝试写一个文件,关闭它,然后打开,但这对我来说不会太多,因为我打开它时必须将文件加载到内存中。

4 个答案:

答案 0 :(得分:3)

为什么不将所有数据写入一个文件并使用“append”选项打开文件?如果您要写入文件中的数据,则无需读入文件中的所有数据。

然而,这可能是一个更好的解决方案:

PrintWriter writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream("data.xml")));

while(rs.next()){
    i++;
    writer.print("\n\t<row>");
    writer.print("\n\t\t<ID>" + Util.transformToHTML(rs.getInt("id")) + "</ID>");
    writer.print("\n\t\t<JED_ID>" + Util.transformToHTML(rs.getInt("jed_id")) + "</JED_ID>");
    writer.print("\n\t\t<IME_PJ>" + Util.transformToHTML(rs.getString("ime_pj")) + "</IME_PJ>");
    //...

    writer.print("\n\t</row>");
}

writer.close();

BufferedOutputStream将在打印数据之前缓冲数据,如果默认值不符合您的需要,您可以在构造函数中指定缓冲区大小。有关详细信息,请参阅Java API:http://java.sun.com/javase/6/docs/api/

答案 1 :(得分:3)

您正在将完整文件组装到内存中:您应该做的是将数据直接写入文件。

此外,您可以考虑使用正确的XML API,而不是将XML组合为文本文件。我们提供了一个简短的教程here

答案 2 :(得分:1)

我从未遇到过这个用例,但我很确定vtd-xml支持大小超过1 GB的xml。值得查看@ http://vtd-xml.sourceforge.net

或者你也可以关注以下所有文章系列@ http://www.ibm.com/developerworks/ “输出大型XML文档”

答案 3 :(得分:0)

好的,所以代码被重写了,我将包括整个操作:

//this is the calling/writing function; I have 8 types of "proizvod" which makes 
//8 XML files. After an XML file is created, it needs to be zipped by a custom zip class
       generateXML(tmpParam,queryRBR,proizvod.getOznaka());
   writeToZip(proizvod.getOznaka());



//inside writeToZip

    ZipEntry ze = new ZipEntry(oznaka + ".xml");
    FileOutputStream fos = new FileOutputStream(new File(zipFolder + oznaka + ".zip"));
    ZipOutputStream zos = new ZipOutputStream(fos);
    zos.putNextEntry(ze);
    FileInputStream fis = new FileInputStream(new File(zipFolder + oznaka + ".xml"));
    final byte[] buffer = new byte[1024];
    int n;
    while ((n = fis.read(buffer)) != -1)
        zos.write(buffer, 0, n);
    zos.closeEntry();
    zos.flush();
    zos.close();
    fis.close();

// inside generateXML
PrintWriter writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(zipFolder +oznaka + ".xml")));
        writer.print("\n<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
        writer.print("\n<PROSTORNE_JEDINICE>");
        stmt = cm.getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, 
                ResultSet.CONCUR_READ_ONLY);
        String q = "";
        rs = stmt.executeQuery(q);
        if(rs != null){

            System.out.println("Početak u : " +Util.nowTime());
            while(rs.next()){
                writer.print("\n\t<row>");
                writer.print("\n\t\t<ID>" + Util.transformToHTML(rs.getInt("id")) + "</ID>");
                writer.print("\n\t\t<JED_ID>" + Util.transformToHTML(rs.getInt("jed_id")) + "</JED_ID>");
              //etc
              writer.print("\n\t</row>");
            }
            System.out.println("Kraj u : " +Util.nowTime());
        }
        writer.print("\n</PROSTORNE_JEDINICE>");

但是generateXML部分仍然占用大量内存(如果我猜对了,它会尽可能多地一点一点)并且我不知道如何优化它(使用另一种方式来提供它writer.print函数)?