2017-05-10 8 views
-1

Excel 파일을 읽은 다음 xssf를 사용하여 CSV 파일에 쓰려고합니다. 메모리 부족 오류가 발생했습니다 (힙 공간). 나는 그 FileInputStream의 메모리 관리를위한 좋은 볼 수 있지만, 여전히 내가 (여기에 내가 1,024메가바이트로 증가) 당신은이 같은 자바 프로세스에 사용 가능한 힙 메모리의 최대 크기를 설정할 수 있습니다 문제를Java FileInputStream 메모리 부족 문제

package xlsxtocsv; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.Locale; 
import org.apache.poi.ss.usermodel.DataFormatter; 
import org.apache.poi.xssf.usermodel.XSSFRow; 
import org.apache.poi.xssf.usermodel.XSSFSheet; 
import org.apache.poi.xssf.usermodel.XSSFWorkbook; 

public class xlsxtocsv 
{ 

    private static final String NEW_LINE_CHARACTER="\r\n"; 

    /** 
    * Write the string into a text file 
    * @param csvFileName 
    * @param csvData 
    * @throws Exception 
    */ 
    private static void writeCSV(String csvFileName,String csvData) throws Exception{ 
     FileOutputStream writer = new FileOutputStream(csvFileName); 
     writer.write(csvData.getBytes()); 
     writer.close(); 
     System.out.println("Sucessfully written data to "+csvFileName); 
    } 


    public static void excelXToCSVfile(String excelFileName,String csvFileName,String Field_Delimiter,int Sheet_Number) { 
     checkValidFile(excelFileName); 
     XSSFWorkbook myWorkBook; 
     try { 
      myWorkBook = new XSSFWorkbook(new FileInputStream(excelFileName)); 

      XSSFSheet mySheet = myWorkBook.getSheetAt(Sheet_Number); 
      String csvData=""; 
      DataFormatter formatter = new DataFormatter(Locale.US); 
      checkValidFile(excelFileName); 

      int rows = mySheet.getPhysicalNumberOfRows(); 
      String prefix="\""; 

      for (int eachRow = 0;eachRow<rows;eachRow++) { 
       XSSFRow myRow = (XSSFRow) mySheet.getRow(eachRow); 
        for (int i=0;i<myRow.getLastCellNum();i++){ 
         if(i==0) 
         { 

          csvData += prefix+formatter.formatCellValue(myRow.getCell(i))+prefix; 

         } 
         else 
         { 
          csvData += Field_Delimiter+prefix+formatter.formatCellValue(myRow.getCell(i))+prefix; 

         } 


        } 
        csvData+=NEW_LINE_CHARACTER; 
      } 




       try { 
        writeCSV(csvFileName, csvData); 
       } catch (Exception e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 

     } catch (FileNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 



     } 


    /** 
    * get Cell value from XLSX file column 
    * @param myCell 
    * @return 
    * @throws Exception 
    */ 

     private static void checkValidFile(String fileName){ 
     boolean valid=true; 
     try{ 
      File f = new File(fileName); 
      if (!f.exists() || f.isDirectory()){ 
       valid=false; 
      } 
     }catch(Exception e){ 
      valid=false; 
     } 
     if (!valid){ 
      System.out.println("File doesn't exist: " + fileName); 
      System.exit(0); 
     } 
    } 
    public static void main(String[] args) throws Exception 
    { 
     String inp_file_name=""; 
     String Output_file_name=""; 
     String delimiter=","; 


     //inp_file_name=args[0];  
     //Output_file_name=args[1]; 

    enter code here 
     //delimiter=args[2]; 


     inp_file_name="C:/Users/xxx/Desktop/cloudera_shared/test_data.xlsx"; 
     Output_file_name="C:/Users/xxx/Desktop/cloudera_shared/test_data.csv"; 
     delimiter="|"; 



    if(args.length==4 && (args[3].equals("") == false)) 
    { 

     int Sheet_Number=Integer.parseInt(args[3]); 
     excelXToCSVfile(inp_file_name,Output_file_name,delimiter,Sheet_Number); 


    } 
    else 
    { 

     excelXToCSVfile(inp_file_name,Output_file_name,delimiter,0); 
    } 

    } 

} 
+0

언제나 안전한 finally 블록에서'fileinputstream'을 닫았다고 가정 해보십시오. 이 [Post] (http://stackoverflow.com/questions/22889075/do-unclosed-streams-cause-memory-leaks-in-java)를 참고하면 도움이 될 것입니다. –

+0

_ "'fileinputstream'은 메모리 관리에 좋습니다"_ - 그 아이디어는 무엇입니까? 두 개념은 서로 관련이 없습니다. 또한 왜 Excel이 이미 수행 한 작업을 복제하고 있습니까? Excel은 xls 파일에서 CSV를 작성할 수 있습니다. –

+0

writeCSV 메소드를 실행할 때 CsvData의 길이는 얼마입니까? – dabaicai

답변

0

를 참조하십시오.

java -Xmx1024m -jar myProgram.jar 

java -X을 실행하면 다른 옵션을 사용할 수 있습니다.

메모리 집약적 인 부분을 더 잘 파악하려면 프로파일 러에서 프로그램을 실행 해보십시오.

+0

3000m에서도 시도했는데 FileOutputStream writer = new FileOutputStream (csvFileName); – Peter

+0

엑셀 파일의 크기는 어느 정도입니까? – Matt

+0

그것은 단지 35 메가 바이트이고 내 시스템은 16 기가 바이트의 램을 가지고 있습니다. – Peter

0

나는 당신에게 코드를 넘어 문제를 제안 할 수 있습니다 :

  1. String csvDataStringBuffer csvData로 교체해야합니다.
  2. 당신은
  3. 당신은이 작업을 실행하기 위해 멀티 스레드을 사용할 수 있습니다 FileOutputStream(nameFile, true) (설정 APPEND가 true) 선언 할 수

    • 첫째 파일은 엑셀에서 내용을 읽을.
    • 2 : 방금 읽은 콘텐츠를 작성하십시오.