有效的方法来读取XLSX文件并将数据存储在Grails中
我需要阅读一个XLSX文件,其中包含5张大约5万行,在Grails中大约7MB。
我需要逐页读取文件,并需要将每行存储到数据库表中。
但我越来越
Java heap space. Stacktrace follows: Message: Executing action [abx] of controller [abc.xyz.controller] caused exception: Runtime error executing action Line | Method ->> 198 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
我试图通过设置“GRAILS_OPTS”来增加堆空间
GRAILS_OPTS=-XX:MaxPermSize=128m -XX:PermSize=128m -Xms1024m -Xmx1024m -XX:-UseGCOverheadLimit
但没有工作。
我遇到了这个问题
如何阅读大小> 40MB的XLSX文件,但没有适当的实现可在这里。
我尝试使用SAX从XLSX文件中读取XML,方法是从如何使用doc
http://poi.apache.org/spreadsheet/how-to.html
Grails控制器:
// // OPCPackage pkg = OPCPackage.open(filename); XSSFReader r = new XSSFReader( pkg ); SharedStringsTable sst = r.getSharedStringsTable(); XMLReader parser1 = XMLReaderFactory.createXMLReader( "org.apache.xerces.parsers.SAXParser" ); ContentHandler handler = new SheetHandler(sst); // //
class SheetHandler.java
class SheetHandler extends DefaultHandler { private SharedStringsTable sst; private String lastContents; private boolean nextIsString; private List<String> rowData private SheetHandler(SharedStringsTable sst) { rowData = [] this.sst = sst; } public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { // c => cell if(name.equals("c")) { // Print the cell reference //System.out.print(attributes.getValue("r") + " - "); // Figure out if the value is an index in the SST String cellType = attributes.getValue("t"); if(cellType != null && cellType.equals("s")) { nextIsString = true; } else { nextIsString = false; } } // Clear contents cache lastContents = ""; } public void endElement(String uri, String localName, String name) throws SAXException { if(name == "row"){ println rowData rowData = [] } // 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")) { rowData << lastContents System.out.println(lastContents); } } public void characters(char[] ch, int start, int length) throws SAXException { lastContents += new String(ch, start, length); } }
通过实施上述我无法区分“标签”从“行xlsx文件”。 我也无法得到列的空值。
我无法正确使用XSSFReader,请帮我解决这个问题。
Shashank你可以使用相同的解决scheme。 为了跳过空单元格,你所要做的就是检查它正在parsing的标签。 这段代码将xlsx转换为带有标签的xml
<r> for row <c> for cell <v> for value
和格式
<r><ct="s" r="A32" s="50"><v>value in the cell</v></c></r> if there is a value in the cell <r><ct="s" r="A32" s="50"></c></r> if there is no value in the cell.
所以,如果有8列的单行,第3列和第5列没有值,那么它将读取xml的顺序将是(只需在startElement和endElement方法中打印variables名称)
r cvvc cvvc cc cvvc cc cvvc cvvc cvvc r
其中cvvc表示
<c><v></v></c>
所以只要检查startElement方法和endElement方法是否具有连续的c作为它的名字,这意味着它有一个空值,然后在rowData中插入一个空白
rowData << ""
您也可以通过传递一个偏移参数到方法并跳过第一个偏移行数来跳过标签行。
希望能帮助到你。