- 后端
【免费下载链接】fesod
Fast. Easy. Done. Processing spreadsheets without worrying about large files causing OOM.
Apache Fesod(Incubating) 的fesod-sheet模块提供了一套以POJO + 注解为核心的电子表格读写 API。本文基于 quickstart/example.md 的官方示例,完整讲解用FesodSheet一个类完成 Excel 读取与写入的最小可运行代码,并结合仓库源码(构建器、监听器、注解实现)深入剖析每条 API 背后的调用链与扩展点。读完本文,你将能在自己的 Maven/Gradle 项目中直接落地「监听式逐行读表」与「注解式模型写表」两套标准用法。
前置准备:引入 fesod-sheet 依赖
fesod-sheet是独立于其他模块发布的核心组件,通过 Maven 引入(版本以 guide.md 中说明的当前版本2.0.2-incubating为准,该版本支持 JDK8 至 JDK25):
<dependency> <groupId>org.apache.fesod</groupId> <artifactId>fesod-sheet</artifactId> <version>2.0.2-incubating</version> </dependency>Gradle 用户对应写法:
dependencies { implementation 'org.apache.fesod:fesod-sheet:2.0.2-incubating' }底层依赖 Apache POI 5.5.1(Excel 处理)、Apache Commons CSV 1.14.1(CSV 支持)与 Ehcache 3.9.11(缓存)。如果你的工程已引入过 POI 相关组件,需要手动排除 POI 相关 jar 以避免版本冲突(详见 guide.md)。
读取电子表格:监听器模式逐行解析
官方示例用「模型类 + 监听器」组合完成读取,核心代码只有一行:
// Implement the ReadListener interface to set up operations for reading data public class DemoDataListener implements ReadListener<DemoData> { @Override public void invoke(DemoData data, AnalysisContext context) { System.out.println("Parsed a data entry" + JSON.toJSONString(data)); } @Override public void doAfterAllAnalysed(AnalysisContext context) { System.out.println("All data parsed!"); } } public static void main(String[] args) { String fileName = "demo.xlsx"; // Read file FesodSheet.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead(); }读表入口:FesodSheet.read 的多种重载
FesodSheet是 Apache Fesod 电子表格处理的核心门面类(源码见 FesodSheet.java),其read方法根据数据来源提供多组重载:
| 重载 | 适用场景 |
|---|---|
read(String pathName) | 按文件路径读取 |
read(File file) | 按文件对象读取 |
read(InputStream inputStream) | 按输入流读取(网络流、上传流等) |
read(pathName/file/inputStream, Class head) | 指定表头模型类 |
read(pathName/file/inputStream, Class head, ReadListener listener) | 指定模型类与读取监听器(示例所用) |
所有重载最终都会构造一个 ExcelReaderBuilder,调用链为read(...)→new ExcelReaderBuilder().file(xxx).headIfNotNull(head).registerReadListenerIfNotNull(listener),即官方示例中的FesodSheet.read(fileName, DemoData.class, new DemoDataListener())等价于:
FesodSheet.read() .file(fileName) // 数据来源 .head(DemoData.class) // 模型类(表头/字段映射依据) .registerReadListener(new DemoDataListener()) // 注册监听器 .sheet() // 选择工作表 .doRead(); // 触发读取监听器核心方法:ReadListener 接口全解
示例中的DemoDataListener实现了 ReadListener 接口。该接口定义了读取过程中的全部生命周期回调,其中invoke与doAfterAllAnalysed是必须实现的两个方法:
void invoke(T data, AnalysisContext context):每解析出一行数据就回调一次。data就是当前行的模型对象(与context.readRowHolder()中持有的行数据一致);context是分析上下文,可从中拿到行号、工作表、工作簿等运行期信息。void doAfterAllAnalysed(AnalysisContext context):所有数据解析完成后回调,常用于收尾(如关闭资源、统计总数、释放分页处理状态)。default void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context):表头行解析完成时回调,可用于校验表头或做动态列名映射。default void onException(Exception exception, AnalysisContext context):任一监听器上报异常时触发;如果在此抛出异常,整个读取过程将终止。default void extra(CellExtra extra, AnalysisContext context):开启额外信息读取(超链接、批注、合并单元格)时回调。default boolean hasNext(AnalysisContext context):控制是否继续读取下一条数据,返回false可提前终止(其默认实现会依据numRows行数上限判断,见 ReadListener.java)。
示例中打印数据使用了JSON.toJSONString(data)(fastjson),这是演示性写法,实际工程中你也可以直接System.out.println(data)或调用 POJO 自身的toString()。
触发读取:sheet().doRead() 的底层链路
.sheet()返回 ExcelReaderSheetBuilder,doRead()内部完成两件事:
public void doRead() { excelReader.read(build()); // 将 ReadSheet 参数交给 ExcelReader 执行 excelReader.finish(); // 收尾并关闭资源 }ExcelReader.read()会根据文件类型(xlsx/xls/csv)选择对应的 SAX 解析器(如XlsxSaxAnalyser、XlsSaxAnalyser)逐行解析,解析出的每一行经转换器(Converter)转换为模型对象后回调invoke——这正是「流式读取、不把整个文件装入内存」的设计基础,也是 Fesod 处理大文件不易 OOM 的关键。相关实现见 analysis/v07/XlsxSaxAnalyser.java 与 analysis/v03/XlsSaxAnalyser.java。
读取常用可选项
通过构建器链,你还可以在sheet()之前或之上附加读取参数:
FesodSheet.read(fileName, DemoData.class, listener) .ignoreEmptyRow(false) // 是否忽略空行,默认 true .numRows(100) // 最多读取 100 行(含表头) .sheet("Sheet1") // 按名称选择工作表 .doRead();sheet()支持无参(默认第一个工作表)、sheet(Integer sheetNo)(从 0 开始的下标)与sheet(String sheetName)(按名称)。其余参数如password(加密文件)、charset(仅 CSV 生效)、readCache(缓存策略,控制内存占用)、extraRead(读取批注/超链接等额外信息)、readDefaultReturn(无模型类时的默认返回类型)等,均可从 ExcelReaderBuilder 查看完整定义。
写入电子表格:注解模型 + 一行写表
官方示例用「注解模型类」描述表头与列,再用一行doWrite落盘:
// Sample data class public class DemoData { @ExcelProperty("String Title") private String string; @ExcelProperty("Date Title") private Date date; @ExcelProperty("Number Title") private Double doubleData; @ExcelIgnore private String ignore; } // Prepare data to write private static List<DemoData> data() { List<DemoData> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { DemoData data = new DemoData(); data.setString("String" + i); data.setDate(new Date()); data.setDoubleData(0.56); list.add(data); } return list; } public static void main(String[] args) { String fileName = "demo.xlsx"; // Create a "Template" sheet and write data FesodSheet.write(fileName, DemoData.class).sheet("Template").doWrite(data()); }模型类注解:@ExcelProperty 与 @ExcelIgnore
写入的核心是模型类上的注解(源码见 ExcelProperty.java):
@ExcelProperty(String[] value()):定义表头名称。写入时若配置多个值会自动合并为多级表头;读取时取最后一个作为列名。示例中@ExcelProperty("String Title")即声明该字段对应名为 "String Title" 的列。@ExcelProperty(index = 2):指定列索引(从 0 开始)。index = -1时按 Java 字段声明顺序排列;字段排序优先级为index > order > 默认声明顺序。@ExcelProperty(order = N):显式指定列排序权重。@ExcelProperty(converter = XxxConverter.class):为该字段强制指定类型转换器,默认走AutoConverter自动匹配。@ExcelIgnore:标记字段完全忽略,不参与读写(源码见 ExcelIgnore.java)。示例中的ignore字段因此不会出现在生成的表格中。
仓库测试模块中可找到对应的模型样本,例如 readwrite/DemoData.java 使用 Lombok 的@Getter/@Setter/@EqualsAndHashCode简化样板代码,并注明「字段顺序与 Excel 列顺序一一对应」——这正是默认排序(index = -1)时的工作机制。
写表入口:FesodSheet.write 的多种重载
与read对称,FesodSheet.write也提供多组重载(源码见 FesodSheet.java):
| 重载 | 适用场景 |
|---|---|
write(String pathName) | 写入文件路径 |
write(File file) | 写入文件对象 |
write(OutputStream outputStream) | 写入输出流(如 HTTP 响应下载) |
write(pathName/file/outputStream, Class head) | 指定表头模型类(示例所用) |
write(...)同样采用构建器模式:new ExcelWriterBuilder().file(xxx).headIfNotNull(head)。写入过程由 ExcelWriterBuilder 配置:
inMemory(Boolean):是否全内存写表,默认false——即默认先写缓存文件再输出,避免大文件 OOM;注释(Comment)与富文本(RichTextString)仅在内存模式下支持。password(String):写加密文件。注意加密需要将整个文件读入内存,非常耗内存。withTemplate(...):基于模板文件写出,模板同样会被读入内存,超大模板可能 OOM。writeExcelOnException(Boolean):即使写出过程中抛异常也保留已生成的文件,默认false。charset(Charset)/withBom(Boolean):仅 CSV 生效,控制编码与 BOM 前缀(避免 Office 打开乱码,默认true)。
指定工作表与触发写出:sheet("Template").doWrite(data())
示例中.sheet("Template")创建名为Template的工作表(sheet(String sheetName)),等价于sheet(Integer sheetNo)按下标或sheet()使用默认表。之后调用doWrite(data())一次性写入整个List<DemoData>。其底层调用链(见 ExcelWriterSheetBuilder.java)为:
excelWriter.write(data, build()); // 执行写入 excelWriter.finish(); // 完成并刷新输出写入时模型类按注解生成表头行,随后逐行通过写转换器(WriteConverter)把字段值转换为单元格内容。ExcelWriterSheetBuilder还提供两个进阶入口:
doWrite(Supplier<Collection<?>> supplier):延迟取数,适合数据量较大、需要按需生成数据的场景。doFill(Object data)/doFill(Object data, FillConfig fillConfig):基于模板做数据填充(fill),对应 write/metadata/fill 下的填充实现。table()/table(Integer tableNo):在同一 sheet 上追加写多张数据表(见 ExcelWriterTableBuilder)。
另外,写入时 sheet 名称会经过长度校验:若超过 MS Excel 允许的最大长度(Workbook.MAX_SENSITIVE_SHEET_NAME_LEN),sensitiveSheetName会将其截断并输出告警日志,防止生成非法文件名(见 ExcelWriterSheetBuilder.java)。
进阶:一行同步读取全部数据
监听器模式适合逐行流式处理;如果你希望像普通方法调用一样直接拿到List<T>,Fesod 提供了同步读取入口(见 ExcelReaderSheetBuilder.java):
List<DemoData> list = FesodSheet.read("demo.xlsx", DemoData.class) .sheet() .doReadSync();doReadSync()内部注册一个内置的SyncReadListener,读取完成后一次性返回结果列表。由于是全量收集到内存,doReadSync()更适合中小文件;大数据量场景仍建议使用监听器模式配合hasNext()/分页读取控制内存。
结合测试:官方读写场景的佐证
仓库测试模块中大量测试直接采用与示例相同模式的 API 调用,可作为学习参照:
- readwrite/DemoDataTest.java:基础模型读写往返测试;
- core/SimpleDataTest.java:最简单模型的无注解读写测试;
- head/ComplexHeadDataTest.java:多级表头(
@ExcelProperty多值合并)场景; - sheet/WriteSheetTest.java:多工作表写入场景。
这些测试展示了从「无注解简单模型」到「复杂表头、多 sheet、填充、样式」的渐进用法,是官方示例之外的最佳扩展阅读材料(完整清单见 website/docs/sheet 目录下的 read/write 专题文档)。
小结
围绕官方 quickstart 示例,本文完整落地了 Fesod Sheet 的两条核心操作链路:
- 读取:
FesodSheet.read(来源, 模型类, 监听器).sheet().doRead(),通过ReadListener的invoke/doAfterAllAnalysed等回调以流式方式逐行消费数据; - 写入:
FesodSheet.write(目标, 模型类).sheet("工作表名").doWrite(数据列表),通过@ExcelProperty/@ExcelIgnore注解声明表头与列映射,构建器内部自动完成生成与落盘。
两者都遵循「门面类 → 构建器 → 执行器」的分层设计,既保证了一行代码的上手体验,又通过构建器暴露了大量可调参数(行数限制、缓存、加密、模板、内存模式等),是进入 Fesod Sheet 更高级特性(样式、合并、填充、自定义转换器)的良好起点。
- 后端
【免费下载链接】fesod
Fast. Easy. Done. Processing spreadsheets without worrying about large files causing OOM.
相关推荐
如何快速上手Apache Fesod:5个高效处理Excel的终极秘诀
如何快速上手Apache Fesod:5个高效处理Excel的终极秘诀 Apache Fesod是一款专门为解决大规模Excel文件处理而设计的高性能Java库
后端Pinpoint JBoss/WildFly 插件接入指南:pinpoint.config 配置、独立/域模式部署与源码原理
Pinpoint JBoss/WildFly 插件接入指南:pinpoint.config 配置、独立/域模式部署与源码原理 导读 本文基于 Pinpoint
后端Apache Fesod入门指南:10分钟学会高性能Excel读写操作
Apache Fesod入门指南:10分钟学会高性能Excel读写操作 Apache Fesod是easyexcel作者最新升级版本,一款快速、简洁、解决大文件
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考