简体   繁体   English

Java - Apache POI - 读取/写入.xlsx 文件 - 文件损坏并变为空

[英]Java - Apache POI - Read/Write .xlsx file - File getting corrupted and becomes empty

I am using a Java program to read and write an existing.xlsx file(same file) but the file is getting corrupted, and the file size becomes zero bytes which is causing "org.apache.poi.EmptyFileException: The supplied file was empty (zero bytes long)” .我正在使用 Java 程序读取和写入现有的.xlsx 文件(同一文件),但文件已损坏,文件大小变为零字节,这导致“org.apache.poi.EmptyFileException:提供的文件为空(零字节长)”

One more thing is - this is not happening consistently.还有一件事是——这种情况并没有持续发生。 The program is reading and writing to file properly most of the time but occurring once out of 10-15 runs.该程序大部分时间都在正确读取和写入文件,但在 10-15 次运行中发生一次。 It would be helpful if anyone has a solution to this.如果有人对此有解决方案,那将很有帮助。 BTW, am using Apache POI 3.13.顺便说一句,我正在使用 Apache POI 3.13。

Read File Program:读取文件程序:

public String getExcelData(String sheetName, int rowNum, int colNum){
    String retVal = null;
    try {
        FileInputStream fis = new FileInputStream("/Absolute/File/Path/Test-File.xlsx");
        Workbook wb = WorkbookFactory.create(fis);
        Sheet s = wb.getSheet(sheetName);
        Row r = s.getRow(rowNum);
        Cell c = r.getCell(colNum);
        retVal=(c.getStringCellValue());
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidFormatException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return retVal;

Write File Program:写文件程序:

public void writeToExcel(String sheetName,int rowNum,int cellNum,String desc){
    try {
        FileInputStream fis = new FileInputStream("/Absolute/File/Path/Test-File.xlsx");
        Workbook wb = WorkbookFactory.create(fis);
        Sheet s = wb.getSheet(sheetName);
        Row r = s.getRow(rowNum);
        Cell c = r.createCell(cellNum);
        c.setCellValue(desc);
        FileOutputStream fos = new FileOutputStream("/Absolute/File/Path/Test-File.xlsx");
        wb.write(fos);
        fos.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidFormatException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Error Trace:错误跟踪:

Exception in thread "main" org.apache.poi.EmptyFileException: The supplied file was empty (zero bytes long)
at org.apache.poi.util.IOUtils.peekFirst8Bytes(IOUtils.java:55)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:201)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:168)
at ExcelLibrary.getExcelData(ExcelLibrary.java:139)
at Driver.main(Driver.java:82)

你需要使用org.apache.commons.io.IOUtils.closeQuietly(fos)和fis关闭FileInputStream和FileOutputStream。

You are reading and writing to the same file at the same time. 您正在同时读取和写入同一文件。 Try to first close FileInputStream fis before writing to FileOutputStream fos. 尝试在写入FileOutputStream fos之前先关闭FileInputStream fis。 Or use temporary file to write new result and then rename it to original one. 或者使用临时文件写入新结果,然后将其重命名为原始结果。

BTW. BTW。 close automatically performs flush, so it don't has to be called separately. close会自动执行flush,因此不必单独调用。

When you write to your file, you seem not to be using flush . 当您写入文件时,您似乎没有使用flush Furthermore, your close code should be done in a finally block to ensure the stream is closed even if something wrong happens. 此外,你的close代码应该做的finally阻塞,以确保即使出现不流被关闭。

As a java dev, you need to use finally block when you use try-catch block. 作为java dev,在使用try-catch块时需要使用finally块。 in your finally block, you must close FileInputStream and FileOutputStream .may be filehandler opened as you didn't close. 在你的finally块中,你必须关闭FileInputStreamFileOutputStream可以在你没有关闭时打开文件处理程序。

I faced this issue initially, solution is simple.我最初遇到这个问题,解决方案很简单。

I am writting only code line which u need to add fis.close();我只写代码行,你需要添加fis.close(); wb.close(); wb.close(); before returning retval在返回retval之前

public String getExcelData(String sheetName, int rowNum, int colNum){
String retVal = null;
try {
    FileInputStream fis = new FileInputStream("/Absolute/File/Path/Test-File.xlsx");
    Workbook wb = WorkbookFactory.create(fis);
    Sheet s = wb.getSheet(sheetName);
    Row r = s.getRow(rowNum);
    Cell c = r.getCell(colNum);
    retVal=(c.getStringCellValue());
    } catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (InvalidFormatException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
fis.close();
wb.close();
return retVal;    
}

Try this one out.试试这个。 I was facing the same issue but resolved it with below.我遇到了同样的问题,但在下面解决了。

FileInputStream fis=new FileInputStream(-Location-);
--- do whatever you want to do --
fis.close();
FileOutputStream fos=new FileOutputStream(-Location-);
wb.write(fos);
fos.close();
wb.close();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM