Java apache POI java.lang.IllegalArgumentException: Position 21504 past the end of the file



I don’t know what am I doing wrong. I’m just reading and writing an Excel file, but always get this exception:

java.lang.IllegalArgumentException: Position 21504 past the end of the file

public class example {
  public static void main(String[] args) throws Exception {
    File destFile = new File("book.xls");
    Workbook destBook = WorkbookFactory.create(destFile);
    try {
        FileOutputStream out = new FileOutputStream(destFile);
        destBook.write(out);
        out.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
  }
}

book.xls exists and has the number “1” in each cell from A1 to L50.

Answer

You are attempting to write the Workbook back to the same file pathname from which it was read. It appears that WorkbookFactory.create doesn’t “release resources” until the Workbook is closed.

Note that in order to properly release resources the Workbook should be closed after use.

When you create the FileOutputStream, you have effectively erased the existing file so that you can write the file data out. However, the Workbook must still rely on the original file being intact. Then, the data to write no longer exists.

You will need to write to a different temporary filename first. Use Apache POI 3.11 or later, so you can call close() on the Workbook, releasing resources.

Close the underlying input resource (File or Stream), from which the Workbook was read. After closing, the Workbook should no longer be used.

This means that the original file must exist until we’re done writing it, so the write must be to another (temporary) file.

File srcFile = new File("book.xls");
File destFile = new File("booktemp.xls");
try {
   Workbook destBook = WorkbookFactory.create(srcFile);
   FileOutputStream out = new FileOutputStream(destFile);
   destBook.write(out);
   out.close();
   destbook.close();  // Available in Apache POI 3.11!
} catch (Exception e) {
   e.printStackTrace();
}

Then you can delete the original file and rename the newly created temporary file to the original name.

boolean deleteSuccess = srcFile.delete();
boolean renameSuccess = destFile.renameTo(srcFile);


Source: stackoverflow