Java-使用Apache POI编写大型Excel文件时发生OutOfMemoryError

Java-使用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

我得到一个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_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中的单独字段,而不是作为“程序参数”

尽管如此,该计划仍有待改进:

  • 逐行处理输入文件
  • 用于写入输出
XSSFWorkbook的流式版本,实现“BigGridDemo”策略。这允许在不耗尽内存的情况下写入非常大的文件,因为在任何时候,只有一部分可配置的行保留在内存中

  • 使用“”而不是新字符串()
  • 与内存无关:正确使用泛型(在解析的CSV中有字符串,而不是任意对象)
请注意,流式传输输入和输出是最好的选择。
话虽如此,按照目前的标准,15MB的输入是很小的,所以我认为稍微提高堆内存不是一个坏的短期解决方案,正如评论中所讨论的,问题是由于IntelliJ运行配置不正确

VM参数需要传递到IntelliJ中的单独字段,而不是作为“程序参数”

尽管如此,该计划仍有待改进:

  • 逐行处理输入文件
  • <