背景
使用了hutool的excel工具类ExcelUtil
现象
org.apache.poi.EmptyFileException: The supplied file was empty (zero bytes long)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:222)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:172)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:280)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:253)
at cn.hutool.poi.excel.WorkbookUtil.createBook(WorkbookUtil.java:84)
at cn.hutool.poi.excel.WorkbookUtil.createSXSSFBook(WorkbookUtil.java:166)
at cn.hutool.poi.excel.WorkbookUtil.createSXSSFBook(WorkbookUtil.java:154)
at cn.hutool.poi.excel.BigExcelWriter.<init>(BigExcelWriter.java:96)
at cn.hutool.poi.excel.BigExcelWriter.<init>(BigExcelWriter.java:86)
at cn.hutool.poi.excel.ExcelUtil.getBigWriter(ExcelUtil.java:395)
日志分析
- 日志表明:加载excel时,原文件为空报错。
代码分析
-
关键业务代码
File tempFile = FileUtil.createTempFile("check-batch-bill", ".xlsx", SystemUtils.getJavaIoTmpDir(), true); ExcelWriter writer = ExcelUtil.getBigWriter(tempFile); writer.write(lists, true);
代码逻辑:
- 创建一个空临时文件。
- excelwriter 关联该空临时文件。
- 将内容写入该空临时文件。
-
源码
ExcelUtil.getBigWriter源码位置
/** * 获得{@link BigExcelWriter},默认写出到第一个sheet,名字为sheet1 * * @param destFile 目标文件 * @return {@link BigExcelWriter} */ public static BigExcelWriter getBigWriter(File destFile) { try { return new BigExcelWriter(destFile); } catch (NoClassDefFoundError e) { throw new DependencyException(ObjectUtil.defaultIfNull(e.getCause(), e), PoiChecker.NO_POI_ERROR_MSG); } } /** * 构造 * * @param destFile 目标文件,可以不存在 * @param sheetName sheet名,做为第一个sheet名并写出到此sheet,例如sheet1 */ public BigExcelWriter(File destFile, String sheetName) { this(destFile.exists() ? WorkbookUtil.createSXSSFBook(destFile) : WorkbookUtil.createSXSSFBook(), sheetName); this.destFile = destFile; } private POIFSFileSystem(FileChannel channel, File srcFile, boolean readOnly, boolean closeChannelOnError) throws IOException { this(false); try { if (srcFile != null) { if (srcFile.length() == 0L) { throw new EmptyFileException(); } FileBackedDataSource d = new FileBackedDataSource(srcFile, readOnly); channel = d.getChannel(); this._data = d; } else { this._data = new FileBackedDataSource(channel, readOnly); } ByteBuffer headerBuffer = ByteBuffer.allocate(512); IOUtils.readFully(channel, headerBuffer); this._header = new HeaderBlock(headerBuffer); this.readCoreContents(); } catch (RuntimeException | IOException var6) { if (closeChannelOnError && channel != null) { channel.close(); } throw var6; } }
报错 部分是:
if (srcFile.length() == 0L) { throw new EmptyFileException(); }
结论:
可以知道,创建空的临时文件是不可行的,而应该指定一个目录。
如
ExcelWriter writer = ExcelUtil.getBigWriter("dir"); writer.write(lists, true);