Как я могу хранить большой объем данных из базы данных в XML (проблема с памятью)? - PullRequest
8 голосов
/ 24 мая 2010

Во-первых, у меня была проблема с получением данных из базы данных, это заняло слишком много памяти и не удалось. Я установил -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 МБ файлов. Теперь я хотел бы, чтобы все эти данные были в одном файле (который я затем сжимаю), но если просто удалить часть if, я выхожу из памяти. Я думал о попытке записать в файл, закрыть его, затем открыть, но это не сильно меня позаботилось, так как при открытии я должен был загрузить файл в память.

Ответы [ 4 ]

3 голосов
/ 24 мая 2010

Вы собираете весь файл в памяти: вам нужно записать данные непосредственно в файл.

Кроме того, вы можете рассмотреть возможность использования правильного XML API, а не собирать XML в виде текстового файла. Краткое руководство доступно здесь .

3 голосов
/ 24 мая 2010

Почему бы не записать все данные в один файл и открыть файл с помощью опции «добавить»? Нет необходимости читать все данные в файле, если вы просто собираетесь записывать в него.

Однако это может быть лучшим решением:

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 буферизует данные перед печатью, и вы можете указать размер буфера в конструкторе, если значение по умолчанию не соответствует вашим потребностям. См. API Java для деталей: http://java.sun.com/javase/6/docs/api/.

1 голос
/ 24 мая 2010

Я никогда не сталкивался с этим сценарием использования, но я уверен, что vtd-xml поддерживает xml размером более 1 ГБ.Стоит проверить @ http://vtd -xml.sourceforge.net

Или вы также можете следить за всеми статьями из серии ниже @ http://www.ibm.com/developerworks/ «Вывод больших XML-документов»

0 голосов
/ 25 мая 2010

Хорошо, поэтому код переписан, и я включу всю операцию:

//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)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...