我正在尝试编写一个相当大的XLSX文件(4百万个单元格),但我有一些内存问题。
我不能使用SXSSF,因为我还需要读取模板中的现有单元格。
我能做些什么来减少内存占用吗<或许可以将流式阅读和流式写作结合起来?
我使用SAX解析器处理XML文档表示的事件。这是
import com.sun.org.apache.xerces.internal.parsers.SAXParser;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class LowMemoryExcelFileReader {
private String file;
public LowMemoryExcelFileReader(String file) {
this.file = file;
}
public List<String[]> read() {
try {
return processFirstSheet(file);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private List<String []> readSheet(Sheet sheet) {
List<String []> res = new LinkedList<>();
Iterator<Row> rowIterator = sheet.rowIterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
int cellsNumber = row.getLastCellNum();
String [] cellsValues = new String[cellsNumber];
Iterator<Cell> cellIterator = row.cellIterator();
int cellIndex = 0;
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
cellsValues[cellIndex++] = cell.getStringCellValue();
}
res.add(cellsValues);
}
return res;
}
public String getFile() {
return file;
}
public void setFile(String file) {
this.file = file;
}
private List<String []> processFirstSheet(String filename) throws Exception {
OPCPackage pkg = OPCPackage.open(filename, PackageAccess.READ);
XSSFReader r = new XSSFReader(pkg);
SharedStringsTable sst = r.getSharedStringsTable();
SheetHandler handler = new SheetHandler(sst);
XMLReader parser = fetchSheetParser(handler);
Iterator<InputStream> sheetIterator = r.getSheetsData();
if (!sheetIterator.hasNext()) {
return Collections.emptyList();
}
InputStream sheetInputStream = sheetIterator.next();
BufferedInputStream bisSheet = new BufferedInputStream(sheetInputStream);
InputSource sheetSource = new InputSource(bisSheet);
parser.parse(sheetSource);
List<String []> res = handler.getRowCache();
bisSheet.close();
return res;
}
public XMLReader fetchSheetParser(ContentHandler handler) throws SAXException {
XMLReader parser = new SAXParser();
parser.setContentHandler(handler);
return parser;
}
/**
* See org.xml.sax.helpers.DefaultHandler javadocs
*/
private static class SheetHandler extends DefaultHandler {
private static final String ROW_EVENT = "row";
private static final String CELL_EVENT = "c";
private SharedStringsTable sst;
private String lastContents;
private boolean nextIsString;
private List<String> cellCache = new LinkedList<>();
private List<String[]> rowCache = new LinkedList<>();
private SheetHandler(SharedStringsTable sst) {
this.sst = sst;
}
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// c => cell
if (CELL_EVENT.equals(name)) {
String cellType = attributes.getValue("t");
if(cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
} else if (ROW_EVENT.equals(name)) {
if (!cellCache.isEmpty()) {
rowCache.add(cellCache.toArray(new String[cellCache.size()]));
}
cellCache.clear();
}
// Clear contents cache
lastContents = "";
}
public void endElement(String uri, String localName, String name)
throws SAXException {
// Process the last contents as required.
// Do now, as characters() may be called more than once
if(nextIsString) {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
nextIsString = false;
}
// v => contents of a cell
// Output after we've seen the string contents
if(name.equals("v")) {
cellCache.add(lastContents);
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
lastContents += new String(ch, start, length);
}
public List<String[]> getRowCache() {
return rowCache;
}
}
}
要处理低内存的大数据,最好的也是我认为唯一的选择是SXSSF api-s。如果您需要读取现有单元的一些数据,我假设您不需要同时读取整个4M。在这种情况下,根据您的应用程序需求,您可以自己处理窗口大小,并在内存中只保留特定时间所需的数据量。您可以从下面的示例开始:http://poi.apache.org/spreadsheet/how-to.html#sxssf
某物作为
SXSSFWorkbook wb = new SXSSFWorkbook(-1); // turn off auto-flushing and accumulate all rows in memory
// manually control how rows are flushed to disk
if(rownum % NOR == 0) {
((SXSSFSheet)sh).flushRows(NOR); // retain NOR last rows and flush all others
希望这有帮助。
我已经编写了用于编写xlsm(Excel2007)的java文件。 使用ApachePOI库,编写xlsx文件是成功的。编写xlsm文件是成功的。但我无法打开xlsm文件,因为打开xlsm文件时出错。 使用ApachePOI库编写xlsm文件可行吗? 如果可以编写xlsm,请提供如何使用ApachePOI库编写xlsm文件的指南。 谢谢
我正在写一个程序,它需要从excel文件中读取和写入数据,而不考虑格式(xls或xlsx)。 我知道ApachePOI,但它似乎有不同的类来处理xls文件(HSSF)和xlsx(XSSF)文件。 任何人都知道我将如何实现我在这里的目标。(也欢迎使用POI以外的API的想法)。
我使用的是ehcache 1.2.3。由于缓存大小是根据“元素”指定的,缓存占用的内存可能会有很大差异(ehcache与hibernate一起使用,并且还保存标准查询缓存,其中查询返回大小可能会有所不同的结果集)。我的问题是:如果JVM内存不足会发生什么。阅读ehcache的变更日志给我的印象是,最初它使用的是软引用,但由于java 1.4正在大力清理它们,软引用最终被删除了。因此,如果缓存太大,
问题内容: 如何使用msgpack对字典进行序列化/反序列化? 问题答案: 在Python文档似乎不是那么好,所以这里是我的尝试。 安装 读写msgpack 对于您的应用程序,以下内容可能很重要: 其他编程语言的支持 阅读/写作表现 紧凑度(文件大小) 另请参阅:数据序列化格式的比较 如果您想寻找一种制作配置文件的方法,则可能需要阅读我的短文《Python中的配置文件》。
嗨,我想在第一行搜索一个字符串,如果找到了,我想移动那一列。
本文向大家介绍使用Python对Excel进行读写操作,包括了使用Python对Excel进行读写操作的使用技巧和注意事项,需要的朋友参考一下 学习Python的过程中,我们会遇到Excel的读写问题。这时,我们可以使用xlwt模块将数据写入Excel表格中,使用xlrd模块从Excel中读取数据。下面我们介绍如何实现使用Python对Excel进行读写操作。 Python版:3.5.2 通过pi