Java .lang.OutOfMemoryError: JAVA HEAP SPACE при преобразовании xlsx в формат csv. Я попытался это не повезло <java -opts> -Xms400m -Xmx4096m - PullRequest
0 голосов
/ 27 января 2020
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.net.*;
import java.util.List;

import com.google.common.base.Joiner;

import org.apache.poi.hssf.usermodel.HSSFCell;
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;

import org.apache.hadoop.fs.*;
import org.apache.hadoop.conf.*;

import static org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted;

public class XlsxToCsv {

    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    private XSSFSheet excelSheet;
    private String outputFile;
    private String defaultFS;
    private List<String[]> arrayCSV = new ArrayList<>();

    // Minumun amount of rows to expect
    private int minRows = 5;

    // Escape char for hive
    private String escapeStr = "\\";

    // Escape char for csv
    private String separatorStr = ",";

    public XlsxToCsv(String inputFile, String outputFile, String excelSheet, String defaultFS) throws IOException {
        this.outputFile = outputFile;
        this.defaultFS = defaultFS;
        this.excelSheet = new XSSFWorkbook(new FileInputStream(inputFile)).getSheet(excelSheet);
    }

    public void setMinRows(int minRows) {
        this.minRows = minRows;
    }

    public void setEscapeStr(String escapeStr) {
        this.escapeStr = escapeStr;
    }

    public void setSeparatorStr(String separatorStr) {
        this.separatorStr = separatorStr;
    }

    public List<String[]> getArrayCSV() {
        return arrayCSV;
    }

    private void convertToCsv() {
        Cell cell;

        try {

            for (Row row : excelSheet) {
                int lastColumnNum = Math.max(row.getLastCellNum(), minRows);
                String[] rowArray = new String[lastColumnNum];

                for (int count = 0; count < lastColumnNum; count++) {
                    cell = row.getCell(count, Row.CREATE_NULL_AS_BLANK);

                    switch (cell.getCellType()) {
                        case HSSFCell.CELL_TYPE_FORMULA:
                            rowArray[count] = isCellDateFormatted(cell) ? dateFormat.format(cell.getDateCellValue()) : Double.toString(cell.getNumericCellValue());
                            break;
                        case Cell.CELL_TYPE_BOOLEAN:
                            rowArray[count] = Boolean.toString(cell.getBooleanCellValue());
                            break;
                        case Cell.CELL_TYPE_NUMERIC:
                            rowArray[count] = isCellDateFormatted(cell) ? dateFormat.format(cell.getDateCellValue()) : Double.toString(cell.getNumericCellValue());
                            break;
                        case Cell.CELL_TYPE_STRING:
                            rowArray[count] = cell.getStringCellValue().replace(separatorStr, escapeStr + separatorStr).replace("\n", " ");
                            break;
                        default:
                            rowArray[count] = "";
                    }
                }

                arrayCSV.add(rowArray);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void writeCsv() {
        try {
            FileSystem fs = FileSystem.get(new URI(defaultFS), new Configuration());
            FSDataOutputStream outputStream = fs.create(new Path(outputFile));

            Joiner joinEmpty = Joiner.on("").skipNulls();
            Joiner joinComma = Joiner.on(separatorStr).skipNulls();

            for (String[] i : arrayCSV) {
                if (joinEmpty.join(i).length() > 0) {
                    outputStream.writeBytes(joinComma.join(i) + "\n");
                }
            }

            outputStream.hflush();
            outputStream.hsync();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) throws IOException {
        String inputFile = args[0];
        String outputFile = args[1];
        String excelSheet = args[2];
        String defaultFS = args[3];

        XlsxToCsv processExcelFile = new XlsxToCsv(inputFile, outputFile, excelSheet, defaultFS);
        processExcelFile.convertToCsv();
        processExcelFile.writeCsv();

        Joiner joinEmpty = Joiner.on("").skipNulls();
        Joiner joinComma = Joiner.on(",").skipNulls();

        for (String[] record : processExcelFile.getArrayCSV()) {
            if (joinEmpty.join(record).length() > 0) {
                System.out.print(joinComma.join(record));
                System.out.print("\n");
            }
        }
    }
}

При преобразовании xlsx в csv я вижу следующее сообщение об ошибке:

Caused by: java.lang.OutOfMemoryError: Java heap space  
at java.io.ByteArrayOutputStream.<init>(ByteArrayOutputStream.java:77)  
at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource$FakeZipEntry.<init>(ZipInputStreamZipEntrySource.java:123)  
at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource.<init>(ZipInputStreamZipEntrySource.java:57)  
at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:93)  
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:278)  
at org.apache.poi.util.PackageHelper.open(PackageHelper.java:37)  
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:274)  
at acvx.agg.qwuer.excel.XlsxToCsv.<init>(XlsxToCsv.java:43)  
at acvx.agg.qwuer.excel.XlsxToCsv.main(XlsxToCsv.java:135)  

1 Ответ

0 голосов
/ 28 января 2020

Некоторые предложения: 1) Я подозреваю, что вы читаете Excel построчно, но после некоторых строк данных может и не быть, и в вашей программе этого нет! 2) Я предлагаю попробовать отредактировать это так, чтобы оно работало только для 50 строк, и вы получите хорошее представление о том, что если у вас больше 250 строк, он может преобразовать эту часть. 3) Если вы добились успеха выше, попробуйте зацикливаться на чтениях и записях, в настоящее время вы читаете все в массив, а затем следующую функцию записи всего. Просто предложив прервать это, скажем, прочитайте 10 и напишите 10. Убедитесь, что после этого вы сделаете ваши переменные равными нулю, чтобы они были доступны для сборки мусора. 4) Увеличение размера затмения зависит от общего объема ОЗУ вашей машины, вы не можете go дальше точка для данной машины, поэтому я согласен, что это не обязательно решит вашу проблему.

...