java.lang.OutOfMemoryError:超出了Excel阅读器的GC开销限制
我得到一个java.lang.OutOfMemoryError:当我尝试运行下面的程序时GC溢出限制超出异常。 该程序的主要方法访问'指定的目录并迭代包含.xlsx的所有文件。 这工作正常,因为我在任何其他逻辑之前测试它。 它调用xlsx的方法基本上可以将xlsx文件转换为csv,并将其附加到现有的文件中。 但是当我把它放在for循环中时,这是当我得到这个异常。 我猜测它有一个冲突,当它打开xlsx并将其转换为csv并打开第二个时间时,也许我必须以某种方式关闭此行:
File inputFile = new File("C:Usersedennis.ADDesktoptest"+nameOfFile);
这是我现在唯一的猜测,即当该文件在循环的第二次迭代到来时发生干扰时。 我正在使用Apache POI库来操纵excel文件。 提前致谢!
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelMan {
public static void main(String[] args) throws FileNotFoundException {
int i =0;
File dir = new File("C:Usersedennis.ADDesktoptest");
for (File child : dir.listFiles()) {
//initializing whether the sheet sent to method is first or not, and //counting iterations for each time the for loop as run
boolean firstSheet = true;
i++;
String nameOfFile = child.getName();
if (nameOfFile.contains(".xlsx")){
System.out.println(nameOfFile);
if (i != 0)
firstSheet = false;
File inputFile = new File("C:Usersedennis.ADDesktoptest"+nameOfFile);
// writing excel data to csv
File outputFile = new File("C:Usersedennis.ADDesktoptestmemb.csv");
xlsx(inputFile, outputFile, firstSheet);
}
// }
}
}
static void xlsx(File inputFile, File outputFile, boolean firstSheet) {
// For storing data into CSV files
StringBuffer data = new StringBuffer();
try {
FileOutputStream fos = new FileOutputStream(outputFile, true);
// Get the workbook object for XLSX file
XSSFWorkbook wBook = new XSSFWorkbook(new FileInputStream(inputFile));
// Get first sheet from the workbook
XSSFSheet sheet = wBook.getSheetAt(7);
Row row;
Cell cell;
// Iterate through each rows from first sheet
java.util.Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext()) {
if (firstSheet != true)
rowIterator.next();
row = rowIterator.next();
// For each row, iterate through each columns
java.util.Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
cell = cellIterator.next();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_BOOLEAN:
data.append(cell.getBooleanCellValue() + "^");
break;
case Cell.CELL_TYPE_NUMERIC:
data.append(cell.getNumericCellValue() + "^");
break;
case Cell.CELL_TYPE_STRING:
data.append(cell.getStringCellValue() + "^");
break;
case Cell.CELL_TYPE_BLANK:
data.append("" + "^");
break;
default:
data.append(cell + "^");
}
}
data.append("rn");
}
fos.write(data.toString().getBytes());
fos.close();
} catch (Exception ioe) {
ioe.printStackTrace();
}
}
}
附加信息:
以下是堆栈跟踪
MR.xlsx
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3039)
at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3060)
at org.apache.xmlbeans.impl.store.Locale$SaxHandler.startElement(Locale.java:3250)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.reportStartTag(Piccolo.java:1082)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseAttributesNS(PiccoloLexer.java:1802)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseOpenTagNS(PiccoloLexer.java:1521)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseTagNS(PiccoloLexer.java:1362)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseXMLNS(PiccoloLexer.java:1293)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseXML(PiccoloLexer.java:1261)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.yylex(PiccoloLexer.java:4808)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.yylex(Piccolo.java:1290)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.yyparse(Piccolo.java:1400)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.parse(Piccolo.java:714)
at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3439)
at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1270)
at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1257)
at org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.parse(SchemaTypeLoaderBase.java:345)
at org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument$Factory.parse(Unknown Source)
at org.apache.poi.xssf.usermodel.XSSFSheet.read(XSSFSheet.java:138)
at org.apache.poi.xssf.usermodel.XSSFSheet.onDocumentRead(XSSFSheet.java:130)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.onDocumentRead(XSSFWorkbook.java:286)
at org.apache.poi.POIXMLDocument.load(POIXMLDocument.java:159)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:207)
at ExcelMan.xlsx(ExcelMan.java:71)
at ExcelMan.main(ExcelMan.java:47)
excel文件相当大,目录中大约有30个左右,最大的大约是170 MB,这些文件大小应该从POI更改?
什么是你的Excel文件的大小? 我曾经有过类似的问题,用xls
创建csv
。 在我的情况下,我不得不切换到事件驱动模型,看看XSSF和SAX(Event API)。 我也用尽了内存(使用-Xmx8g
)
来自链接网站的引用:
HSSF的进一步努力将集中在以下主要领域:
文件不需要关闭。 只要你没有保持对它们的引用,它们将会在GCd超出范围之外。
行if (i != 0)
将始终计算为true,因为您正在将该变量i至少增加一次,然后才能触及此条件。 因此firstSheet始终设置为false。
该线
File inputFile = new File("C:Usersedennis.ADDesktoptest"+nameOfFile);
正在创建新文件。 但是,您已经有一个由child
代表的此路径的文件对象
你总是在写同一个文件,你重新创建一个文件对象和新的FileOutputStream,以便每次迭代子目录时,尽管所有的写操作都在同一个文件中。
你不会在finally块中关闭FileOutputStream,并且在错误条件下可能无法正确关闭FileOutputStream。
除非您需要同步方法来构建字符串,否则请使用StringBuilder而不是StringBuffer。
考虑使用FileWriter而不是中间的StringBuilder。 而不是写入Builder使用
PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(outputFile, true))))
而不是使用data.append
使用writer.print
或writer.println
注意:PrintWriter和Buffered Writer包装并非绝对必要,但很有用。
如果你参考XSSFWorkbook javadocs的构造函数选项,你会看到它说:“使用InputStream比使用File需要更多的内存,所以如果一个File可用,那么你应该做一些事情,比如'example following''http:// poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFWorkbook.html#XSSFWorkbook(java.io.InputStream)
如果一切都失败了,增加堆的大小可能是一个可行的解决方案。 假设您没有比当前测试的文件大得多的文件。 增加Java中的堆大小
链接地址: http://www.djcxy.com/p/75023.html上一篇: java.lang.OutOfMemoryError: GC overhead limit exceeded excel reader