Java-使用Apache POI编写大型Excel文件时发生OutOfMemoryError
我得到一个java outofmemory错误。我添加了必要的java参数,但仍然不断出现此错误。我共享了我使用的库和函数。该函数在将大型csv文件(约15mb)转换为xlsx文件时出现此错误。它可以在小文件上正常工作,没有任何错误。如何修复此错误?谢谢 MainJava-使用Apache POI编写大型Excel文件时发生OutOfMemoryError,java,csv,apache-poi,out-of-memory,xlsx,Java,Csv,Apache Poi,Out Of Memory,Xlsx,我得到一个java outofmemory错误。我添加了必要的java参数,但仍然不断出现此错误。我共享了我使用的库和函数。该函数在将大型csv文件(约15mb)转换为xlsx文件时出现此错误。它可以在小文件上正常工作,没有任何错误。如何修复此错误?谢谢 Main public class Main { public static void main(String[] args) { convert_CSV_to_XLSX(S.CSV_PATH,S.XLSX_P
public class Main {
public static void main(String[] args) {
convert_CSV_to_XLSX(S.CSV_PATH,S.XLSX_PATH,"Sheet");
}
}
将CSV转换为XLSX
public void convert_CSV_to_XLSX(String inputFilePath, String outputFilePath, String sheetName) {
try {
ArrayList<ArrayList<Object>> csvObjectsAll = readCSV(inputFilePath);
writeXLSX_horizontally(outputFilePath, csvObjectsAll, sheetName);
} catch (Exception e) {
e.printStackTrace();
}
}
public void writeXLSX_horizontally(String outputFileName, ArrayList<ArrayList<Object>> gdl, String sheetName) {
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet(sheetName);
int rowNum = 0;
for (ArrayList<Object> objectArrList : gdl) {
Row row = sheet.createRow(rowNum++);
int cellNum = 0;
for (Object obj : objectArrList) {
Cell cell = row.createCell(cellNum++);
boolean is_double = false, is_integer = false;
try {
cell.setCellValue(Double.parseDouble(obj.toString()));
is_double = true;
} catch (Exception e) {
}
if (!is_double) {
try {
cell.setCellValue(Integer.parseInt(obj.toString()));
is_integer = true;
} catch (Exception e) {
}
}
if (!is_double && !is_integer) {
if (obj == null) {
cell.setCellValue(new String());
} else {
cell.setCellValue(obj.toString());
}
}
}
}
try {
FileOutputStream file = new FileOutputStream(outputFileName);
workbook.write(file);
file.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void writeXLSX_horizontally(String outputFileName, ArrayList<ArrayList<Object>> gdl, String sheetName) {
SXSSFWorkbook workbook = new SXSSFWorkbook();
SXSSFSheet sheet = workbook.createSheet(sheetName);
int rowNum = 0;
for (ArrayList<Object> objectArrList : gdl) {
Row row = sheet.createRow(rowNum++);
int cellNum = 0;
for (Object obj : objectArrList) {
Cell cell = row.createCell(cellNum++);
boolean is_double = false, is_integer = false;
try {
cell.setCellValue(Double.parseDouble(obj.toString()));
is_double = true;
} catch (Exception e) { }
if (!is_double)
try {
cell.setCellValue(Integer.parseInt(obj.toString()));
is_integer = true;
} catch (Exception e) { }
if (!is_double && !is_integer)
if (obj == null)
cell.setCellValue(new String());
else
cell.setCellValue(obj.toString());
}
}
try {
FileOutputStream file = new FileOutputStream(outputFileName);
workbook.write(file);
file.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void将\u CSV\u转换为\u XLSX(字符串inputFilePath、字符串outputFilePath、字符串sheetName){
试一试{
ArrayList csvObjectsAll=readCSV(inputFilePath);
水平写入(outputFilePath、csvObjectsAll、sheetName);
}捕获(例外e){
e、 printStackTrace();
}
}
ReadCSV
public ArrayList<ArrayList<Object>> readCSV(String inputFilePath) {
ArrayList<ArrayList<Object>> gal = new ArrayList<>();
try {
String csvStr = new String(Files.readAllBytes(Paths.get(inputFilePath)), StandardCharsets.UTF_8);
for (String str : csvStr.split("\n")) {
ArrayList<Object> csvLinesSplit = new ArrayList<>();
String ss = str.replaceAll("\"", "");
if (ss.charAt(ss.length() - 1) == ',') {
ss += "$";
}
for (String s : ss.split(",")) {
if (s.equals("") || s.equals("$")) {
csvLinesSplit.add("");
} else {
csvLinesSplit.add(s);
}
}
gal.add(csvLinesSplit);
}
} catch (Exception e) {
}
return gal;
}
public ArrayList<ArrayList<Object>> readCSV(String inputFilePath) {
ArrayList<ArrayList<Object>> gal = new ArrayList<>();
try {
BufferedReader csvReader = new BufferedReader(new FileReader(inputFilePath));
String row;
int rowSize = 0;
ArrayList<String> columnList = new ArrayList<>();
while ((row = csvReader.readLine()) != null) {
ArrayList<Object> rowCells = new ArrayList<>();
if (rowSize == 0) {
if (row.charAt(row.length() - 1) == ',')
throw new Exception("CSV Format Error");
for (String columnName : row.split(",")) {
columnList.add(columnName);
}
}
int cellSize = 0;
for (String cell : row.split(",")) {
if (cell.equals("")) {
rowCells.add(null);
} else {
rowCells.add(cell);
}
cellSize++;
}
if (cellSize != columnList.size()) {
for (int i = 0; i < columnList.size() - cellSize; i++) {
rowCells.add(null);
}
}
gal.add(rowCells);
rowSize++;
}
} catch (Exception e) {
e.printStackTrace();
}
return gal;
}
public ArrayList readCSV(字符串inputFilePath){
ArrayList gal=新的ArrayList();
试一试{
String csvStr=新字符串(Files.readAllBytes(path.get(inputFilePath)),StandardCharsets.UTF_8);
对于(字符串str:csvStr.split(“\n”)){
ArrayList csvLinesSplit=新的ArrayList();
字符串ss=str.replaceAll(“\”,“”);
如果(ss.charAt(ss.length()-1)==','){
ss+=“$”;
}
用于(字符串s:ss.split(“,”){
如果(s.equals(“”)| s.equals($){
csvLinesSplit.添加(“”);
}否则{
CSV线分裂添加;
}
}
gal.add(csvLinesSplit);
}
}捕获(例外e){
}
返回gal;
}
写入XLSX
public void convert_CSV_to_XLSX(String inputFilePath, String outputFilePath, String sheetName) {
try {
ArrayList<ArrayList<Object>> csvObjectsAll = readCSV(inputFilePath);
writeXLSX_horizontally(outputFilePath, csvObjectsAll, sheetName);
} catch (Exception e) {
e.printStackTrace();
}
}
public void writeXLSX_horizontally(String outputFileName, ArrayList<ArrayList<Object>> gdl, String sheetName) {
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet(sheetName);
int rowNum = 0;
for (ArrayList<Object> objectArrList : gdl) {
Row row = sheet.createRow(rowNum++);
int cellNum = 0;
for (Object obj : objectArrList) {
Cell cell = row.createCell(cellNum++);
boolean is_double = false, is_integer = false;
try {
cell.setCellValue(Double.parseDouble(obj.toString()));
is_double = true;
} catch (Exception e) {
}
if (!is_double) {
try {
cell.setCellValue(Integer.parseInt(obj.toString()));
is_integer = true;
} catch (Exception e) {
}
}
if (!is_double && !is_integer) {
if (obj == null) {
cell.setCellValue(new String());
} else {
cell.setCellValue(obj.toString());
}
}
}
}
try {
FileOutputStream file = new FileOutputStream(outputFileName);
workbook.write(file);
file.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void writeXLSX_horizontally(String outputFileName, ArrayList<ArrayList<Object>> gdl, String sheetName) {
SXSSFWorkbook workbook = new SXSSFWorkbook();
SXSSFSheet sheet = workbook.createSheet(sheetName);
int rowNum = 0;
for (ArrayList<Object> objectArrList : gdl) {
Row row = sheet.createRow(rowNum++);
int cellNum = 0;
for (Object obj : objectArrList) {
Cell cell = row.createCell(cellNum++);
boolean is_double = false, is_integer = false;
try {
cell.setCellValue(Double.parseDouble(obj.toString()));
is_double = true;
} catch (Exception e) { }
if (!is_double)
try {
cell.setCellValue(Integer.parseInt(obj.toString()));
is_integer = true;
} catch (Exception e) { }
if (!is_double && !is_integer)
if (obj == null)
cell.setCellValue(new String());
else
cell.setCellValue(obj.toString());
}
}
try {
FileOutputStream file = new FileOutputStream(outputFileName);
workbook.write(file);
file.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void writeXLSX_水平(String outputFileName、ArrayList gdl、String sheetName){
XSSFWorkbook工作簿=新XSSFWorkbook();
XSSFSheet sheet=workbook.createSheet(sheetName);
int rowNum=0;
for(ArrayList对象ArrList:gdl){
Row-Row=sheet.createRow(rowNum++);
int-cellNum=0;
用于(对象对象对象:对象列表){
Cell Cell=row.createCell(cellNum++);
布尔值为_double=false,为_integer=false;
试一试{
cell.setCellValue(Double.parseDouble(obj.toString());
是双=真;
}捕获(例外e){
}
如果(!是双精度){
试一试{
setCellValue(Integer.parseInt(obj.toString());
is_integer=true;
}捕获(例外e){
}
}
如果(!is_double&&!is_integer){
if(obj==null){
setCellValue(新字符串());
}否则{
cell.setCellValue(obj.toString());
}
}
}
}
试一试{
FileOutputStream文件=新的FileOutputStream(outputFileName);
工作簿。编写(文件);
file.close();
}捕获(例外e){
e、 printStackTrace();
}
}
此行:
String csvStr = new String(Files.readAllBytes(Paths.get(inputFilePath)), StandardCharsets.UTF_8);
问题:
您正在使用Files.readAllBytes
将整个文件加载到内存中,并且为运行此程序的jvm处理器分配的内存不足
可能的解决方案:
您可能希望使用诸如BufferedReader之类的流/缓冲区开始读取文件。或者,您可以查找其他读取器,这些读取器允许您以位读取文件,这样就不会一次性消耗整个内存
进一步修改:
您必须在编写时修改您的程序,在读取数据位后,处理并写入文件,当再次写入文件时,添加此行。
String csvStr = new String(Files.readAllBytes(Paths.get(inputFilePath)), StandardCharsets.UTF_8);
问题:
您正在使用Files.readAllBytes
将整个文件加载到内存中,并且为运行此程序的jvm处理器分配的内存不足
可能的解决方案:
您可能希望使用诸如BufferedReader之类的流/缓冲区开始读取文件。或者,您可以查找其他读取器,这些读取器允许您以位读取文件,这样就不会一次性消耗整个内存
进一步修改:
您必须在编写时修改您的程序,在读取数据位后,处理并写入文件,当再次写入文件时,添加。正如注释中所述,问题是由于IntelliJ运行配置不正确 VM参数需要传递到IntelliJ中的单独字段,而不是作为“程序参数” 尽管如此,该计划仍有待改进:
- 逐行处理输入文件
- 用于写入输出
- 使用“”而不是新字符串()
- 与内存无关:正确使用泛型(在解析的CSV中有字符串,而不是任意对象)
话虽如此,按照目前的标准,15MB的输入是很小的,所以我认为稍微提高堆内存不是一个坏的短期解决方案,正如评论中所讨论的,问题是由于IntelliJ运行配置不正确 VM参数需要传递到IntelliJ中的单独字段,而不是作为“程序参数” 尽管如此,该计划仍有待改进:
- 逐行处理输入文件 <