XLSX到CSV内存不足错误

时间:2014-09-18 12:17:37

标签: java excel csv xlsx xssf

我找到了很多解决方案如何使用Java将XLSX转换为CSV文件,所有解决方案都使用:XSSFWorkbook。我面临的问题是,流可能包含太多数据。我只是不明白为什么,文件只有4mb。

CODE:

// For storing data into CSV files
    StringBuffer data = new StringBuffer();
    try {
        FileOutputStream fos = new FileOutputStream(outputFile);
        System.out.println("Getting input stream.");
        // Get the workbook object for XLS file
        XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(inputFile));
        System.out.println(" - Done");
        // Get first sheet from the workbook
        XSSFSheet sheet = workbook.getSheetAt(0);
        Cell cell;
        Row row;

        // Iterate through each rows from first sheet
        Iterator<Row> rowIterator = sheet.iterator();
        System.out.println(" - Reading xlsx rows.");
        while (rowIterator.hasNext()) {
            i++;

            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('\n');
            int limit = 10000;
            if ((i % limit) == 0) {
                System.out.println(" - Writing " + limit + " data.");
                fos.write(data.toString().getBytes());
                fos.flush();
                data = null;
                data = new StringBuffer();
                System.out.println(" - Data written.");
            }
        }

        fos.write(data.toString().getBytes());
        fos.flush();
        fos.close();

错误指向switch语句中的行,我将数据附加到数据(StringBuffer),但我将其置零,因此它不应该是一个问题。

3 个答案:

答案 0 :(得分:0)

现在您可能无法使用SXSSFWorkbook(因为它是只写的),但您可以使用SAX-based API将程序转换为流式。编辑:您可能想要尝试的另一件事是从File而不是InputStream创建XSSFWorkbook(我记得在某处读取基于文件的代码需要更少的内存)。

(首先尝试: 由于您按顺序读取数据,因此SXSSFWorkbook类应该是您需要的。)

答案 1 :(得分:0)

xlsx格式只是一个包含内容xml和共享字符串xml的zip。因此4 MB压缩,可能非常大,未压缩。

使用zip文件系统,您可以将共享字符串加载到内存中,然后按顺序读取内容xml,立即输出。

作为两个内部文件,您可以使用java的zip文件系统。繁琐而不困难。

答案 2 :(得分:0)

尝试这段代码,对我来说这是完美的工作,希望对您也有用。

package com.converting;

import java.io.FileInputStream;
import java.io.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.opencsv.CSVWriter;
import java.util.Iterator;
import java.io.FileWriter;

public class XlsxtoCSV {

        public static void main(String[] args) throws Exception{
             FileInputStream input_document = new FileInputStream(new File("/home/blackpearl/Downloads/aa.xlsx"));
             XSSFWorkbook my_xls_workbook = new XSSFWorkbook(input_document); 
             XSSFSheet  my_worksheet = my_xls_workbook.getSheetAt(0); 

             Iterator<Row> rowIterator = my_worksheet.iterator();
             FileWriter my_csv=new FileWriter("/home/blackpearl/Downloads/Newaa.csv");
             CSVWriter my_csv_output=new CSVWriter(my_csv); 
             while(rowIterator.hasNext()) {
                     Row row = rowIterator.next(); 
                     int i=0;//String array
                     String[] csvdata = new String[20];
                     Iterator<Cell> cellIterator = row.cellIterator();
                             while(cellIterator.hasNext()) {
                                     Cell cell = cellIterator.next(); //Fetch CELL
                                     switch(cell.getCellType()) { //Identify CELL type
                                     case Cell.CELL_TYPE_STRING:
                                             csvdata[i]= cell.getStringCellValue();                                              
                                             break;
                                     }
                                     i=i+1;
                             }
             my_csv_output.writeNext(csvdata);
             }
             System.out.println("file imported");
             my_csv_output.close(); //close the CSV file
             input_document.close(); //close xlsx file
     }
}