我是java的新手。我只是想了解如何处理堆内存溢出及其原因。有人可以帮我下面的代码为什么它会抛出这个错误。我怎么能避免它。
错误:
线程“main”中的异常java.lang.OutOfMemoryError:Java堆空间 在java.util.Arrays.copyOf(Arrays.java:2361)at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:117) 在 java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:406) 在java.lang.StringBuffer.append(StringBuffer.java:237)at com.ugam.qa.tittle.XlsxToCsv.xlsx(XlsxToCsv.java:49)at at com.ugam.qa.tittle.XlsxToCsv.main(XlsxToCsv.java:77)
package com.ugam.qa.tittle;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Iterator;
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 XlsxToCsv {
static void xlsx(File inputFile, File outputFile) {
// For storing data into CSV files
StringBuffer data = new StringBuffer();
try {
FileOutputStream fos = new FileOutputStream(outputFile);
// Get the workbook object for XLSX file
XSSFWorkbook wBook = new XSSFWorkbook(new FileInputStream(inputFile));
// Get first sheet from the workbook
XSSFSheet sheet = wBook.getSheetAt(0);
Row row;
Cell cell;
// Iterate through each rows from first sheet
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext()) {
row = rowIterator.next();
{
// For each row, iterate through each columns
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("\r\n");
}}
}
fos.write(data.toString().getBytes());
fos.close();
} catch (Exception ioe) {
ioe.printStackTrace();
}
}
//testing the application
public static void main(String[] args) {
//reading file from desktop
File inputFile = new File("D:\\files\\listing\\test.xlsx");
//writing excel data to csv
File outputFile = new File("D:\\files\\listing\\test1.csv");
xlsx(inputFile, outputFile);
}
}
答案 0 :(得分:3)
增加堆是一种解决方案:java -Xmx<MegaBytes>M <YourClass>
更好的解决方案是使用更少的内存,这在您的情况下很容易:为什么要在将整个输出存储到流中之前将其存储在StringBuffer
中?在您找到它们时,将每个部分直接写入流将会更加节省内存。
您的代码的另一个改进是使用FileWriter
而不是FileOutputStream
:它可以让您控制输出编码,并直接接受字符串,而无需您调用String#getBytes()
。
答案 1 :(得分:2)
首先(虽然与内存消耗无关),您正在创建一个文本文件,因此请使用FileWriter
而不是FileOutputStream
。
FileWriter writer = new FileWriter(outputFile);
其次,您正在内存中构建一个非常长的字符串。显然这会占用大量内存。最好构造程序,以便在读取输入文件时生成输出文件,而不会在内存中累积所有内容。例如,替换:
data.append(cell.getBooleanCellValue() + ",");
与
writer.write(cell.getBooleanCellValue() + ",");
答案 2 :(得分:1)
只需使用
运行您的应用程序java -Xmx<whatever value in megs/gigs> yourApp
答案 3 :(得分:0)
在解析xlsx文件时我也遇到了同样的OOM问题......经过两天的挣扎,我终于找到了下面非常完美的代码;
此代码基于sjxlsx。它读取xlsx并存储在HSSF表中。
// read the xlsx file
SimpleXLSXWorkbook = new SimpleXLSXWorkbook(new File("C:/test.xlsx"));
HSSFWorkbook hsfWorkbook = new HSSFWorkbook();
org.apache.poi.ss.usermodel.Sheet hsfSheet = hsfWorkbook.createSheet();
Sheet sheetToRead = workbook.getSheet(0, false);
SheetRowReader reader = sheetToRead.newReader();
Cell[] row;
int rowPos = 0;
while ((row = reader.readRow()) != null) {
org.apache.poi.ss.usermodel.Row hfsRow = hsfSheet.createRow(rowPos);
int cellPos = 0;
for (Cell cell : row) {
if(cell != null){
org.apache.poi.ss.usermodel.Cell hfsCell = hfsRow.createCell(cellPos);
hfsCell.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_STRING);
hfsCell.setCellValue(cell.getValue());
}
cellPos++;
}
rowPos++;
}
return hsfSheet;