【问题标题】:Java FileInputStream out of memory issueJava FileInputStream 内存不足问题
【发布时间】:2017-10-08 11:57:07
【问题描述】:

我正在尝试读取一个 excel 文件,然后使用 xssf 写入 csv 文件。我出现内存不足错误(堆空间)。我看到 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);
    }

    }

}

【问题讨论】:

  • 假设您在 finally 块中关闭 fileinputstream,这始终是安全的。参考这个post 它可能会有所帮助。
  • "fileinputstream 有利于内存管理" - 是什么让你有这个想法?这两个概念是不相关的。另外,你为什么要复制 Excel 已经做的事情? Excel 非常有能力从 xls 文件写入 CSV。
  • 执行 writeCSV 方法时 CsvData 的长度是多少?

标签: java memory memory-management out-of-memory


【解决方案1】:

我可以建议你代码之外的问题:

  1. String csvData 应替换为 StringBuffer csvData。
  2. 可以声明FileOutputStream(nameFile, true)(设置追加为真)
  3. 你可以使用多线程来执行2个任务:

    • 首先:从您的 excel 文件中读取内容。
    • 二:写刚刚读过的内容。

【讨论】:

    【解决方案2】:

    您可以像这样设置 Java 进程可用的最大堆内存大小(这里我将其增加到 1024 MB)。

    java -Xmx1024m -jar myProgram.jar
    

    如果您运行java -X,您可以看到不同的可用选项。

    尝试在分析器中运行您的程序,以更好地了解哪些部分是内存密集型的。

    【讨论】:

    • 我什至尝试了 3000m ,但没有改善它说 FileOutputStream writer = new FileOutputStream(csvFileName); 内存不足;
    • 你的 excel 文件有多大?
    • 只有 35 mb,我的系统有 16 GB 的内存
    猜你喜欢
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    • 2019-03-18
    • 2015-04-15
    • 2019-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多