Java 如何将大量数据从数据库存储到XML(内存问题)?
首先,我在从数据库获取数据时遇到问题,占用了太多内存,因此失败了。我已经设置了-Xmx1500M,我正在使用滚动结果集,这样就可以解决这个问题了。现在我需要从数据中生成一个XML,但我不能将它放在一个文件中。目前,我是这样做的:Java 如何将大量数据从数据库存储到XML(内存问题)?,java,oracle,Java,Oracle,首先,我在从数据库获取数据时遇到问题,占用了太多内存,因此失败了。我已经设置了-Xmx1500M,我正在使用滚动结果集,这样就可以解决这个问题了。现在我需要从数据中生成一个XML,但我不能将它放在一个文件中。目前,我是这样做的: while(rs.next()){ i++; xmlStringBuilder.append("\n\t<row>"); xmlStringBuilder.app
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();
}
while(rs.next()){
i++;
xmlStringBuilder.append(“\n\t”);
xmlStringBuilder.append(“\n\t\t”+Util.transformToHTML(rs.getInt(“id”)+”);
xmlStringBuilder.append(“\n\t\t”+Util.transformToHTML(rs.getInt(“jed_id”)+”);
xmlStringBuilder.append(“\n\t\t”+Util.transformToHTML(rs.getString(“ime_pj”))+”);
//等等。
xmlStringBuilder.append(“\n\t”);
如果(i%100000==0){
//将数据存储到名为i.xml的文件中
storeKBR(xmlStringBuilder.toString(),i);
xmlStringBuilder=null;
xmlStringBuilder=新的StringBuilder();
}
现在,我想做的是把所有的数据放在一个文件中(然后压缩)但是如果只是删除if部分,我的内存就会耗尽。我曾想过尝试写入一个文件,关闭它,然后打开,但这不会让我有多大的收获,因为打开文件时我必须将文件加载到内存中。为什么不将所有数据写入一个文件,然后用“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();
PrintWriter writer=new PrintWriter(new BufferedOutputStream(new FileOutputStream(“data.xml”));
while(rs.next()){
i++;
writer.print(“\n\t”);
writer.print(“\n\t\t”+Util.transformToHTML(rs.getInt(“id”)+”);
writer.print(“\n\t\t”+Util.transformToHTML(rs.getInt(“jed_id”))+”);
writer.print(“\n\t\t”+Util.transformToHTML(rs.getString(“ime_pj”))+”);
//...
writer.print(“\n\t”);
}
writer.close();
BufferedOutputStream将在打印数据之前对数据进行缓冲,如果默认值不适合您的需要,您可以在构造函数中指定缓冲区大小。有关详细信息,请参阅java API:。您正在内存中组装完整的文件:您应该做的是将数据直接写入文件
另外,您可以考虑使用适当的XML API,而不是将XML组装为文本文件。简短的教程是可用的。
< P>我从来没有遇到过这个用例,但我非常肯定VTD XML支持的大小超过1 GB的XML。 或者您也可以阅读以下所有系列文章@“输出大型XML文档”好的,因此代码被重写,我将包括整个操作:
//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>");
//这是调用/写入函数;我有8种类型的“proizvod”,它使
//8个XML文件。创建XML文件后,需要通过自定义zip类对其进行压缩
generateXML(tmpParam、queryRBR、proizvod.getOznaka());
writeToZip(proizvod.getOznaka());
//内部writeToZip
ZipEntry ze=新的ZipEntry(oznaka+“.xml”);
FileOutputStream fos=新的FileOutputStream(新文件(zipFolder+oznaka+“.zip”);
ZipoutStream zos=新ZipoutStream(fos);
佐斯·普特内森特里(泽);
FileInputStream fis=新的FileInputStream(新文件(zipFolder+oznaka+“.xml”);
最终字节[]缓冲区=新字节[1024];
int n;
而((n=fis.read(buffer))!=-1)
写入(缓冲区,0,n);
zos.closeEntry();
zos.flush();
zos.close();
fis.close();
//内生成XML
PrintWriter writer=新的PrintWriter(新的BufferedOutputStream(新的FileOutputStream(zipFolder+oznaka+“.xml”));
writer.print(“\n”);
writer.print(“\n”);
stmt=cm.getConnection().createStatement(ResultSet.TYPE\u SCROLL\u不敏感,
结果集CONCUR_只读);
字符串q=“”;
rs=标准执行程序(q);
如果(rs!=null){
System.out.println(“Početak u:+Util.nowTime());
while(rs.next()){
writer.print(“\n\t”);
writer.print(“\n\t\t”+Util.transformToHTML(rs.getInt(“id”)+”);
writer.print(“\n\t\t”+Util.transformToHTML(rs.getInt(“jed_id”))+”);
//等
writer.print(“\n\t”);
}
System.out.println(“Kraj u:+Util.nowTime());
}
writer.print(“\n”);
但是generateXML部分仍然占用大量内存(如果我猜对了,它会尽可能地一点一点地占用内存),我不知道如何优化它(使用另一种方式为writer.print函数提供数据)?这听起来不错,但我不确定如何做。这是我当前的代码fos=new FileOutputStream(new File)(zipFolder+i+“.xml”);fos.write(xmlString.getBytes());fos.flush();fos.close();它仍然需要1.5 GB的RAM,但我能处理的内存太多了:)谢谢,我很高兴你能让它工作起来,但总的来说,这类任务没有理由不能在64M内存中完成:从数据库中流式传输结果是第一步(),并将其直接写入文件是第二部分。事情是,我在周六继承了该应用程序,它必须在周一之前运行,因此我没有太多的操作空间:)一旦完成,我将重构该应用程序并返回给您。也感谢您的评论。Andrija,Daniel的解决方案不应该占用太多内存-可能一种方法是使用XMLAPI写入多个xml文件,然后使用文件i/o合并所有文件的内容?