我要求执行以下操作
1)复制一个巨大的Excel文件1400 * 1400并制作副本。
2)读取复制的文件并添加新的列和行,同时进行编辑。
3)这将是一个独立的程序,而不是在服务器上。我有内存占用少,性能快的局限性。
我做了一些阅读并找到了以下内容
1)没有API来复制一个巨大的文件
2)SXSSF可用于写作但不能用于阅读
3)XSSF和SAX(事件API)可用于阅读但不能用于编辑。如果我再次尝试读取和存储为对象,则会出现内存问题。
请帮助我如何做到这一点?
答案 0 :(得分:1)
假设您的内存大小足以使用XSSF / SAX读取和SXSSF写入,请允许我建议以下解决方案。
1)使用XSSF / SAX读取文件。对于每一行,使用行数据创建一个对象,并使用ObjectOutputStream或您认为方便的任何其他输出格式立即将其写入文件。您将为每行创建单独的文件。并且内存中只有1个行对象,因为您可以继续使用每行的数据修改同一个对象。
2)进行所需的任何修改。对于需要修改的行,请将相应的文件读回行对象,根据需要进行修改,然后将其写回。对于新行,只需在行对象中设置数据并将其写入新文件即可。
3)使用SXSSF重新组合电子表格,方法是一次读取1行目标文件并将其存储在输出电子表格中。
这样,你一次只能在内存中占一行。
答案 1 :(得分:1)
如果有大量数据由于“超出内存”或“超出GC限制”而发生,并且内存有问题,则数据最初可以解析为xml文件。可以使用xml文件替换excel表,以便最小化内存使用量。
在excel中,工作表表示为xml。使用java.util.zip.ZipFile可以识别每个条目。工作表的xml可以用解析的xml替换,以便我们在Excel工作表中获得预期的数据。
以下类可用于创建xml文件:
public class XmlSpreadsheetWriter {
private final Writer _out;
private int _rownum;
public XmlSpreadsheetWriter(Writer out){
_out = out;
}
public void beginSheet() throws IOException {
_out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">" );
_out.write("<sheetData>\n");
}
public void endSheet() throws IOException {
_out.write("</sheetData>");
_out.write("</worksheet>");
}
public void insertRow(int rownum) throws IOException {
_out.write("<row r=\""+(rownum+1)+"\">\n");
this._rownum = rownum;
}
public void endRow() throws IOException {
_out.write("</row>\n");
}
public void createCell(int columnIndex, String value, int styleIndex) throws IOException {
String ref = new CellReference(_rownum, columnIndex).formatAsString();
_out.write("<c r=\""+ref+"\" t=\"inlineStr\"");
_out.write(" s=\""+styleIndex+"\"");
_out.write(">");
_out.write("<is><t>"+value+"</t></is>");
_out.write("</c>");
}
public void createCell(int columnIndex, double value, int styleIndex) throws IOException {
String ref = new CellReference(_rownum, columnIndex).formatAsString();
_out.write("<c r=\""+ref+"\" t=\"n\"");
_out.write(" s=\""+styleIndex+"\"");
_out.write(">");
_out.write("<v>"+value+"</v>");
_out.write("</c>");
}
public void createEmptyCell(int columnIndex, int styleIndex)throws IOException {
String ref = new CellReference(_rownum, columnIndex).formatAsString();
_out.write("<c r=\""+ref+"\" t=\"n\"");
_out.write(" s=\""+styleIndex+"\"");
_out.write(">");
_out.write("<v></v>");
_out.write("</c>");
}
}
答案 2 :(得分:0)
如果内存是处理您指出的记录数(即1400 * 1400)的问题,那么获取XML数据并处理这些数据可能是您的解决方案。我知道它可能不是最好的解决方案,但它肯定会满足您的低内存要求。甚至POI网站也指出了这个解决方案:
“如果内存占用是个问题,那么对于XSSF,您可以获取基础XML数据并自行处理。这适用于愿意学习.xlsx的一些低级结构的中间开发人员。文件,以及谁喜欢在java中处理XML。它使用相对简单,但需要对文件结构有基本的了解。提供的优点是你可以读取内存占用相对较小的XLSX文件。“