Java读取Excel并写入的核心方案是结合Apache POI或EasyExcel库,通过流式处理或内存映射技术实现高效的数据解析与持久化,其中EasyExcel因低内存占用更适合大数据量场景。
在数据驱动的时代,Excel依然是企业间流转信息最通用的载体,无论是财务对账、库存盘点还是用户数据迁移,Java开发者经常面临将非结构化或半结构化的表格数据转化为程序可处理对象的任务,过去,开发者往往依赖老旧的API,导致在处理万级甚至百万级数据时频繁遭遇内存溢出,选择合适的工具链并掌握正确的读写策略,能让这一过程变得既稳定又高效。
技术选型:POI与EasyExcel的深度对比
选择正确的库是项目成功的基石,业内专家指出,不同场景下对性能和资源的需求差异巨大,盲目追求“最新”或“最流行”往往适得其反。
Apache POI的传统优势与局限
Apache POI是Java操作Office文档的事实标准,支持.xls和.xlsx格式,它的优势在于功能全面,能够精确控制单元格样式、公式计算以及图表嵌入,对于需要精细排版或复杂公式计算的报表生成场景,POI依然是首选。
POI的短板也显而易见,它在解析Excel时会将整个工作簿加载到内存中,据统计,处理超过1万行数据时,JVM堆内存占用会显著上升,在服务器资源有限的生产环境中,这极易引发OutOfMemoryError错误,POI的API设计较为繁琐,编写样板代码较多,开发效率相对较低。
EasyExcel的轻量化革命
针对POI的痛点,阿里巴巴开源的EasyExcel应运而生,它基于POI底层,但采用了单元格事件解析模式,实现了“边读边写”的流式处理机制。
- 内存占用极低:无论Excel文件多大,内存占用始终保持在MB级别,轻松应对百万级数据导入。
- API简洁直观:通过注解映射实体类,开发者只需关注数据模型,无需关心底层XML解析细节。
- 生态兼容性好:完美支持Spring Boot集成,且对.xlsx格式支持优异,对老旧.xls格式支持有限。
对于大多数业务系统的数据导入导出需求,EasyExcel已成为行业共识中的主流选择。
实战指南:Java读取Excel数据
读取Excel的核心在于将表格中的每一行数据映射为Java对象,以下以EasyExcel为例,展示标准的数据读取流程。
环境依赖配置
在Maven项目中,引入核心依赖是第一步,确保版本稳定,避免使用SNAPSHOT版本进行生产部署。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.2</version>
</dependency>
定义数据模型
使用注解定义Excel列与Java字段的对应关系。@ExcelProperty注解中的索引或名称决定了映射规则。
@Data
public class UserExcelData {
@ExcelProperty("姓名")
private String name;
<pre><code>@ExcelProperty("年龄")
private Integer age;
@ExcelProperty("邮箱")
private String email;
执行读取操作
调用read方法,传入文件路径、数据类以及监听器,监听器负责处理每一行数据的回调逻辑。
EasyExcel.read("users.xlsx", UserExcelData.class, new PageReadListener<UserExcelData>(dataList -> {
// 每页处理逻辑,例如批量入库
for (UserExcelData data : dataList) {
System.out.println(data.getName());
}
})).sheet().doRead();
这种分页读取的方式,既保证了内存安全,又提高了处理吞吐量。
高效写入:构建结构化Excel文件
写入操作通常用于生成报表或导出数据,与读取不同,写入更关注数据的组装和样式的控制。
基础写入流程
使用write方法,指定输出路径和数据类,通过withTemplate方法可以实现基于模板的填充,这种方式在财务报表生成中尤为常见,因为它能保留复杂的表头设计和公式。
大数据量写入优化
当数据量达到十万级以上时,同步写入可能导致页面超时,此时应启用异步写入或分批写入策略。
- 分批写入:将数据分割成多个小批次,每次写入后刷新输出流,避免一次性构建庞大的内存对象树。
- 异步线程池:利用线程池并行处理数据转换,主线程仅负责接收结果并写入文件,提升整体响应速度。
常见坑点与解决方案
在写入过程中,开发者常遇到日期格式错乱或数字精度丢失的问题,解决方案是在实体类字段上添加@DateTimeFormat注解,指定具体的日期格式,如”yyyy-MM-dd HH:mm:ss”,对于金额字段,建议使用BigDecimal类型,并配合@NumberFormat注解确保精度。
Q&A:Java读取Excel并写入常见问题解析
Java读取Excel并写入时如何处理特殊字符和乱码?
乱码问题通常源于编码不一致,Excel文件在Windows下默认使用GBK编码,而在Linux服务器或某些编辑器中可能保存为UTF-8,在读取时,EasyExcel默认使用UTF-8,若遇到GBK编码的.xls文件,需在read方法中显式指定charset为Charset.forName(“GBK”),对于写入,建议统一使用UTF-8编码保存文件,并在前端下载时设置正确的Content-Type头,避免浏览器解析错误。
Java读取Excel并写入过程中出现OOM(内存溢出)怎么办?
OOM是大数据量处理中的头号杀手,首先检查是否使用了POI的SXSSFWorkbook以外的模式,SXSSFWorkbook虽支持流式写入,但读取仍需全量加载,确认是否使用了EasyExcel的流式读取监听器,避免将所有数据加载到List中,检查实体类中是否存在大对象引用,如图片二进制数据,应将其移除或仅存储路径,若数据量极大,建议分片处理,每次只读取和处理固定行数,处理完即释放内存。
Java读取Excel并写入能否实现复杂样式的保留与修改?
EasyExcel主要关注数据层面的读写,对样式的精细控制能力弱于POI,若需保留原有Excel的复杂样式(如合并单元格、条件格式、图表),最佳实践是“模板填充”,即预先制作好带有样式的Excel模板,程序中仅填充数据,若需动态修改样式,可结合POI的底层API,在EasyExcel写入完成后,通过POI读取生成的文件进行样式微调,但这会牺牲部分性能,对于纯数据导出,建议放弃样式保留,直接生成标准格式文件,以提升处理速度。
首发原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/453455.html



