核心思路
无论使用哪个库,导出到指定路径的核心思路都是一样的:

- 创建一个
java.io.File对象:用你想要保存的完整文件路径来初始化这个对象。 - 检查/创建目录:确保文件所在的目录存在,如果不存在,就创建它,这可以避免
FileNotFoundException。 - 创建输出流:基于
File对象创建一个文件输出流(FileOutputStream)。 - 使用 Excel 库写入数据:将 Excel 内容写入到这个输出流中。
- 关闭资源:非常重要,关闭输出流以释放系统资源。
主流 Excel 库对比
目前最主流的 Java Excel 库有三个,各有优缺点:
| 库名 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Apache POI | 功能最强大,支持 .xls (旧版) 和 .xlsx (新版) 格式,几乎所有功能都能实现。 |
API 相对繁琐,代码量较多,内存消耗大(特别是处理大文件时)。 | 需要复杂格式、图表、公式等高级功能,或处理旧版 .xls 文件。 |
| EasyExcel | API 极其简洁,基于 POI 封装,性能好(特别是大文件导出时采用 SAX 模式),内存占用低。 | 功能相比 POI 稍弱,但对于绝大多数导出需求绰绰有余。 | 强烈推荐,特别是简单的数据导出、Web 接口下载等场景。 |
| JXL (Java Excel API) | 非常轻量,API 简单,速度快。 | 已停止更新多年,不支持 .xlsx 格式,功能有限。 |
仅用于维护老旧项目或处理简单的 .xls 文件。不推荐新项目使用。 |
下面我将分别展示使用这三个库导出 Excel 到指定路径的完整代码。
场景设定
假设我们要导出一个简单的用户信息列表到 D:/temp/users.xlsx 路径。
数据模型:

public class User {
private String name;
private String email;
private Integer age;
// 构造器、Getter 和 Setter
public User(String name, String email, Integer age) {
this.name = name;
this.email = email;
this.age = age;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
}
使用 Apache POI 导出 Excel
1 添加 Maven 依赖
<dependencies>
<!-- Apache POI 核心依赖 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<!-- Apache POI OOXML 依赖,用于处理 .xlsx 文件 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
</dependencies>
2 完整代码示例
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class PoiExportExample {
public static void main(String[] args) {
// 1. 准备数据
List<User> userList = new ArrayList<>();
userList.add(new User("张三", "zhangsan@example.com", 28));
userList.add(new User("李四", "lisi@example.com", 32));
userList.add(new User("王五", "wangwu@example.com", 24));
// 2. 定义导出路径
String filePath = "D:/temp/users_poi.xlsx";
File file = new File(filePath);
try {
// 3. 确保目录存在
File parentDir = file.getParentFile();
if (parentDir != null && !parentDir.exists()) {
System.out.println("目录不存在,正在创建: " + parentDir.getAbsolutePath());
parentDir.mkdirs(); // 创建多级目录
}
// 4. 创建 Workbook 和 Sheet
// XSSFWorkbook 用于 .xlsx 格式
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("用户信息");
// 5. 创建表头
Row headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue("姓名");
headerRow.createCell(1).setCellValue("邮箱");
headerRow.createCell(2).setCellValue("年龄");
// 6. 填充数据
int rowNum = 1;
for (User user : userList) {
Row row = sheet.createRow(rowNum++);
row.createCell(0).setCellValue(user.getName());
row.createCell(1).setCellValue(user.getEmail());
row.createCell(2).setCellValue(user.getAge());
}
// 7. 写入文件
try (FileOutputStream fos = new FileOutputStream(file)) {
workbook.write(fos);
System.out.println("Excel 文件已成功导出到: " + file.getAbsolutePath());
}
// 8. 关闭 Workbook
workbook.close();
} catch (IOException e) {
System.err.println("导出 Excel 文件时发生错误: " + e.getMessage());
e.printStackTrace();
}
}
}
使用 EasyExcel 导出 Excel (推荐)
1 添加 Maven 依赖
<dependencies>
<!-- EasyExcel 核心依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.1</version>
</dependency>
</dependencies>
2 完整代码示例
EasyExcel 的优势在于无需手动创建表头和数据行,只需要一个数据模型类和一个监听器。
2.1 数据模型类 (User.java)
需要添加 ExcelProperty 注解来指定列名。
import com.alibaba.excel.annotation.ExcelProperty;
public class User {
// value = "姓名" 对应 Excel 中的列名
@ExcelProperty("姓名")
private String name;
@ExcelProperty("邮箱")
private String email;
@ExcelProperty("年龄")
private Integer age;
// 必须提供一个无参构造器
public User() {}
public User(String name, String email, Integer age) {
this.name = name;
this.email = email;
this.age = age;
}
// Getter 和 Setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
}
2.2 导出主程序
import com.alibaba.excel.EasyExcel;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class EasyExcelExportExample {
public static void main(String[] args) {
// 1. 准备数据
List<User> userList = new ArrayList<>();
userList.add(new User("张三", "zhangsan@example.com", 28));
userList.add(new User("李四", "lisi@example.com", 32));
userList.add(new User("王五", "wangwu@example.com", 24));
// 2. 定义导出路径
String filePath = "D:/temp/users_easyexcel.xlsx";
File file = new File(filePath);
try {
// 3. 确保目录存在
File parentDir = file.getParentFile();
if (parentDir != null && !parentDir.exists()) {
System.out.println("目录不存在,正在创建: " + parentDir.getAbsolutePath());
parentDir.mkdirs();
}
// 4. 使用 EasyExcel 写入文件
// EasyExcel.write(文件路径, 数据模型类.class).sheet("工作表名").doWrite(数据集合);
EasyExcel.write(file, User.class).sheet("用户信息").doWrite(userList);
System.out.println("Excel 文件已成功导出到: " + file.getAbsolutePath());
} catch (Exception e) {
System.err.println("导出 Excel 文件时发生错误: " + e.getMessage());
e.printStackTrace();
}
}
}
对比:可以看到,EasyExcel 的代码量大大减少,逻辑也更清晰,非常适合快速开发。
使用 JXL 导出 Excel (不推荐新项目)
1 添加 Maven 依赖
<dependencies>
<!-- JXL 依赖 -->
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.12</version>
</dependency>
</dependencies>
2 完整代码示例
JXL 只能生成 .xls 格式。
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class JxlExportExample {
public static void main(String[] args) {
// 1. 准备数据
List<User> userList = new ArrayList<>();
userList.add(new User("张三", "zhangsan@example.com", 28));
userList.add(new User("李四", "lisi@example.com", 32));
userList.add(new User("王五", "wangwu@example.com", 24));
// 2. 定义导出路径 (注意后缀是 .xls)
String filePath = "D:/temp/users_jxl.xls";
File file = new File(filePath);
try {
// 3. 确保目录存在
File parentDir = file.getParentFile();
if (parentDir != null && !parentDir.exists()) {
System.out.println("目录不存在,正在创建: " + parentDir.getAbsolutePath());
parentDir.mkdirs();
}
// 4. 创建 WritableWorkbook 和 WritableSheet
WritableWorkbook workbook = Workbook.createWorkbook(file);
WritableSheet sheet = workbook.createSheet("用户信息", 0);
// 5. 添加表头
sheet.addCell(new Label(0, 0, "姓名"));
sheet.addCell(new Label(1, 0, "邮箱"));
sheet.addCell(new Label(2, 0, "年龄"));
// 6. 填充数据
for (int i = 0; i < userList.size(); i++) {
User user = userList.get(i);
sheet.addCell(new Label(0, i + 1, user.getName()));
sheet.addCell(new Label(1, i + 1, user.getEmail()));
sheet.addCell(new Label(2, i + 1, user.getAge().toString()));
}
// 7. 写入并关闭文件
workbook.write();
workbook.close();
System.out.println("Excel 文件已成功导出到: " + file.getAbsolutePath());
} catch (IOException | WriteException e) {
System.err.println("导出 Excel 文件时发生错误: " + e.getMessage());
e.printStackTrace();
}
}
}
总结与最佳实践
- 首选 EasyExcel:对于绝大多数 Java 项目,尤其是 Web 项目中需要生成报表或提供下载功能时,EasyExcel 是最佳选择,它简单、高效、内存友好。
- POI 用于复杂场景:如果你的 Excel 需要包含复杂的样式、图表、公式、图片插入等高级功能,那么必须使用 Apache POI。
- 路径处理是关键:在写入文件前,务必检查并创建父目录,这是健壮代码的体现,使用
file.getParentFile().mkdirs()是一个标准做法。 - 资源管理:使用
try-with-resources语句(如try (FileOutputStream fos = ...))可以自动关闭流,防止资源泄漏,这是现代 Java 编程的推荐做法。 - 异常处理:文件操作是 I/O 操作,可能会抛出
IOException,务必进行捕获和处理,避免程序意外终止。
