2010-05-24 26 views
8

İlk olarak, Veritabanından veri almakla ilgili bir sorun yaşadım, çok fazla bellek aldı ve başarısız oldu. -Xmx1500M'yi ayarlıyorum ve kaydımlı ResultSet kullanıyorum, bu yüzden halledildi. Şimdi verilerden bir XML almam gerekiyor, ancak bir dosyaya koyamıyorum. Şu anda bunu şu şekilde yapıyorum:Büyük miktarda veriyi veritabanından XML'e (bellek sorunu) nasıl kaydedebilirim?

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(); 
       } 

ve çalışıyor; 12 100 MB dosya alıyorum. Şimdi, yapmak istediğim şey, tüm bu verilere tek bir dosyada sahip olmaktır (ki daha sonra sıkıştırıyorum) ama eğer parçayı kaldırırsam, bellekten çıkarım. Bir dosyaya yazmayı, kapatmayı, sonra açmayı düşündüm ama açıldığımda dosyayı belleğe yüklemek zorunda kalmamdan çok fazla şey almazdı.

+0

Bunu yapmanın bir yolu - xml api kullanarak birden fazla xml dosyasına yazı yazmak ve daha sonra dosya i/o kullanarak tüm dosyaların içeriğini birleştirmek olurdu? – Inv3r53

cevap

3

Neden tüm verileri bir dosyaya yazmıyorsunuz ve dosyayı "append" seçeneği ile açıyorsunuz? Sadece yazacaksanız, dosyadaki tüm verilerin okunmasına gerek yoktur.

Ancak bu daha iyi bir çözüm olabilir: BufferedOutputStream yazdırmadan önce verileri tamponlayacaktır

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(); 

ve varsayılan değer ihtiyaçlarınızı karşılayacak etmezse yapıcı metotta tampon boyutunu belirtebilirsiniz. Ayrıntılar için java API'sine bakın: http://java.sun.com/javase/6/docs/api/.

+0

Bu kulağa hoş geliyor ama nasıl yapılacağından emin değilim. Bu şu andaki kodum fos = new FileOutputStream (yeni Dosya (zipFolder + i + ".xml")); fos.write (xmlString.getBytes()); fos.flush(); fos.close(); – Andrija

+0

Halen 1.5 GB RAM alır ama o kadar çok şey halledebilirim :) Teşekkür ederim – Andrija

+0

Çalıştığına sevindim, ama genel olarak, bu tür bir görevin 64M belleğinde tamamlanmasının bir nedeni yok: akış sonuçları DB'yi oluşturan ilk adımdır (http://javaquirks.blogspot.com/2007/12/mysql-streaming-result-set.html) ve bunları doğrudan bir dosyaya yazmanız ikinci kısımdır. –

3

Tüm dosyayı bellekte birleştiriyorsunuz: yapmanız gereken, verileri doğrudan dosyaya yazmaktır. Ayrıca, XML'i bir metin dosyası olarak oluşturmak yerine, uygun bir XML API'sini kullanmayı düşünebilirsiniz. Kısa bir eğitici kullanılabilir here.

0

Tamam @ tüm aşağıdaki makale serisini takip edebilir, böylece kod yeniden yazılır ve bütün operasyonu ekleriz:

//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>"); 

Ama generateXML kısmı hala çok fazla bellek alır (Ben doğru tahmin ediyorsam, o kadar olabildiğince yavaş yavaş sürer) ve ben bunun (alternatif kullanma optimize nasıl görmüyorum writer.print işlevini beslemenin yolu)?

İlgili konular