Java读取Excel文件常用Apache POI和EasyExcel库,Apache POI支持xls/xlsx格式,通过Workbook、Sheet、Row、Cell对象遍历数据;EasyExcel采用SAX模式读取,内存占用更低,适合大数据量,需引入依赖,处理文件流异常,循环读取单元格内容并转为业务对象,适用于数据导入、报表生成等场景,需注意版本兼容性和性能优化。
Java读取Excel文件的实用指南与代码示例
在数据处理和业务系统中,Excel文件凭借其通用性和易用性,已成为数据存储与交换的重要载体,Java作为企业级开发的主流语言,经常需要实现Excel文件的读取功能,例如批量导入数据、报表解析、历史数据迁移等,本文将详细介绍Java中读取Excel文件的两种主流方式——基于Apache POI和阿里巴巴EasyExcel,并提供具体代码示例,帮助开发者快速上手。
常用Java读取Excel库对比
在Java生态中,处理Excel文件的开源库主要有以下两种,各有特色:
| 特性 | Apache POI | EasyExcel(阿里开源) |
|---|---|---|
| 支持格式 | .xls(HSSF)、.xlsx(XSSF) |
.xls、.xlsx、.csv |
| 内存占用 | 较高(尤其处理大文件时) | 极低(基于SAX模式,流式读取) |
| 功能丰富度 | 强(支持复杂格式、图表、公式等) | 适中(聚焦核心读写,注解简化开发) |
| 性能表现 | 中等,大文件处理容易OOM | 优秀,百万级数据稳定运行 |
| 学习成本 | 中等(需熟悉HSSF/XSSF API) | 较低(注解+监听器模式,代码简洁) |
| 社区支持 | 成熟,文档丰富 | 活跃,阿里官方维护 |
选择建议:
- 小文件(<10MB)或需处理复杂格式(如公式、图表、宏)时,优先选择Apache POI;
- 大文件(>50MB)或追求高性能开发,推荐EasyExcel;
- 新项目或注重开发效率,建议使用EasyExcel。
使用Apache POI读取Excel
Apache POI是Java操作Office文档的经典库,支持Excel的读写,本文以最新稳定版(POI 5.2.5)为例,介绍读取.xlsx(Excel 2007+)和.xls(Excel 2003)文件的方法。
环境准备
在Maven项目的pom.xml中添加依赖:
<dependencies>
<!-- POI核心依赖 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
<!-- OOXML支持(.xlsx格式) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
<!-- 日期处理支持 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-lite</artifactId>
<version>5.2.5</version>
</dependency>
</dependencies>
读取.xlsx文件(XSSFWorkbook)
.xlsx基于Open XML格式,使用XSSFWorkbook类操作,以下示例读取Excel中的所有数据并打印:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.IOException;
public class PoiReadExcel {
public static void main(String[] args) {
String filePath = "data.xlsx"; // Excel文件路径
try (FileInputStream fis = new FileInputStream(filePath);
Workbook workbook = new XSSFWorkbook(fis)) {
// 获取第一个Sheet页
Sheet sheet = workbook.getSheetAt(0);
// 遍历每一行(跳过标题行)
for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
Row row = sheet.getRow(rowNum);
if (row == null) continue;
// 遍历每一个单元格
for (int cellNum = 0; cellNum < row.getLastCellNum(); cellNum++) {
Cell cell = row.getCell(cellNum);
if (cell == null) continue;
// 根据单元格类型获取值
String value = getCellValueAsString(cell);
System.out.print(value + "\t");
}
System.out.println();
}
} catch (IOException e) {
System.err.println("读取Excel失败:" + e.getMessage());
e.printStackTrace();
}
}
// 将单元格值转换为字符串(兼容不同类型)
private static String getCellValueAsString(Cell cell) {
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
// 处理数字(避免整数变成科学计数法)
if (DateUtil.isCellDateFormatted(cell)) {
return cell.getDateCellValue().toString();
} else {
// 处理整数和小数
double numericValue = cell.getNumericCellValue();
return numericValue % 1 == 0 ?
String.valueOf((long) numericValue) :
String.valueOf(numericValue);
}
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case FORMULA:
return cell.getCellFormula();
case BLANK:
return "";
default:
return "";
}
}
}
读取.xls文件(HSSFWorkbook)
.xls是Excel 97-2003格式,使用HSSFWorkbook类,代码结构与.xlsx类似,只需将XSSFWorkbook替换为HSSFWorkbook:
// 替换workbook的创建方式 Workbook workbook = new HSSFWorkbook(fis);
POI读取注意事项
- 资源管理:
Workbook和FileInputStream必须使用try-with-resources关闭,避免内存泄漏; - 单元格类型:Excel单元格可能为字符串、数字、日期等,需通过
getCellType()判断类型后处理; - 空值处理:需判断
Row和Cell是否为null,避免空指针异常; - 日期格式:使用
DateUtil.isCellDateFormatted()判断是否为日期格式; - 性能优化:大文件时考虑使用
SXSSFWorkbook(流式API)减少内存占用。
使用EasyExcel读取Excel(推荐)
EasyExcel是阿里巴巴开源的Excel处理工具,通过SAX模式(流式读取)解决了POI内存占用高的问题,尤其适合大文件读取,其核心优势是注解映射和监听器模式,代码更简洁,性能更优越。
环境准备
Maven依赖(EasyExcel 3.3.2):
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.2</version>
</dependency>
定义数据模型(注解映射)
通过@ExcelProperty注解将Excel列与Java对象属性绑定:
import com.alibaba.excel.annotation.ExcelProperty;
import java.util.Date;
public class UserData {
@ExcelProperty("姓名")
private String name;
@ExcelProperty("年龄")
private Integer age;
@ExcelProperty("生日")
private Date birthday;
@ExcelProperty("邮箱")
private String email;
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public Date getBirthday() { return birthday; }
public void setBirthday(Date birthday) { this.birthday = birthday; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
监听器模式读取数据
EasyExcel使用监听器模式实现流式读取,内存占用极低:
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;
public class EasyExcelReadDemo {
public static void main(String[] args) {
String fileName = "user_data.xlsx";
// 直接读取到List
List<UserData> dataList = EasyExcel.read(fileName)
.head(UserData.class)
.sheet()
.doReadSync();
System.out.println("读取到的数据量:" + dataList.size());
dataList.forEach(System.out::println);
// 使用监听器模式(推荐大文件