2014-09-18 7 views
1

Я нашел множество решений, как конвертировать XLSX в CSV-файл с использованием Java, все решения используют: XSSFWorkbook. Проблема, с которой я сталкиваюсь, заключается в том, что, вероятно, поток имеет слишком много данных. Я просто не понимаю почему, файл всего 4 Мб.Ошибка XLSX в CSV

КОД:

// 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(); 

Ошибка указывает на строку на коммутаторе заявление, где я добавляющим что-то к данным (StringBuffer), но я обнулять его, чтобы он не должен быть проблемой.

+1

Вы наполняете вещи в «StringBuffer», которые могут быть не такими эффективными. Зачем хранить его в памяти? Просто создайте одну строку, напишите это для файла и перейдите (вы, вероятно, захотите использовать «BufferedWriter» .Кроме того, почему вы создаете String и преобразуете его в 'byte []' next, что дублирует след памяти. скорость вашего JVM и GC вы получаете много дополнительных объектов. Одна вещь, которую нужно попытаться начать, - это снизить лимит, а вместо того, чтобы создавать новый 'StringBuffer', просто его пустить и повторно использовать. Вместо' StringBUffer' I предложите использовать 'StringBuilder'. –

+0

Да, до того, как я использовал только setLength (0), но проблемы там не было, это было во время fileInputStream. –

+1

Большие объекты могут задерживаться, чтобы повторное использование могло быть лучше. происходит, когда чтение не означает, что это из-за чтения. Ваша память заполняется, и большой «StringBuffer» будет моим первым исправлением. Еще одно замечание: вы используете 'StringBuffer', но все еще используете String concat для добавления Строки. Предлагаю удалить ' + ";" из вашего оператора case и добавить 'data.append (';')' после операторов case. Сохраняет создание дополнительной строки для concat. –

ответ

0

Теперь вы не сможете использовать SXSSFWorkbook (так как это только для записи), но вы можете конвертировать вашу программу в потоковый стиль, используя SAX-based API. Изменить: Еще одна вещь, которую вы можете попробовать, - создать XSSFWorkbook из файла вместо InputStream (я помню, где-то читал, что в коде на основе файлов требуется меньше памяти).

(Первая попытка была: Поскольку вы читаете данные последовательно SXSSFWorkbook класс должен быть только то, что вам нужно.)

+0

SXSSFWorkbook только для записи, проверьте: http://stackoverflow.com/questions/12513981/reading-data-from-xlsx-with-apache-pois-sxssfsheet –

+0

Но спасибо в любом случае. –

0

Формат XLSX просто зип с XML контентом и разделяемой строк XML. Следовательно, сжатый 4 МБ, может быть очень большой несжатый.

Используя zip-файловую систему, вы можете загрузить общие строки в память, а затем прочитать содержимое xml последовательно, сразу же вывести.

Как два внутренних файла, вы можете использовать zip-файловую систему java. Довольно утомительно, но не сложно.