别再与 Apache POI 纠缠——认识 Sheetz,这个 Java 的一行代码 Excel 库
Source: Dev.to
如果你曾经在 Java 中处理 Excel 文件,你一定很熟悉以下流程:
- 引入 Apache POI。
- 为了读取一列标题而编写数十行的样板代码。
- 接下来花一个小时调试第 14 行的
NullPointerException,因为有人留下了空单元格。
听起来很熟悉吧?
Sheetz 是一个开源的 Java 库,它将所有这些痛苦压缩成一行代码:
List products = Sheetz.read("products.xlsx", Product.class);
没有样板代码。没有繁琐的步骤。只有数据。
为什么选择 Sheetz?
Apache POI 功能强大,但它并非为开发者的易用性而设计。
EasyExcel、FastExcel 和 Poiji 更好,但仍然需要相当多的配置。
Sheetz 采用不同的理念:默认零配置,需要时可完全控制。
开箱即用功能
| ✅ | 特性 |
|---|---|
| 🚀 | 单行 API – Sheetz.read()、Sheetz.write(),搞定 |
| 📊 | 真正的 SAX 流式处理 – 使用约 10 MB 恒定内存处理百万行文件 |
| 🔄 | 自动类型转换 – 19 个内置转换器(日期、枚举、BigDecimal、UUID,……) |
| 🧵 | 线程安全 – 可安全并发使用 |
| ✅ | 内置校验 – 提供带行/列上下文的详细错误报告 |
| 📝 | 注解映射 – @Column 用于自定义表头、必填字段、默认值等 |
依赖
Maven
io.github.chitralabs.sheetz
sheetz-core
1.0.1
Gradle
implementation 'io.github.chitralabs.sheetz:sheetz-core:1.0.1'
简单 POJO
public class Product {
public String name;
public Double price;
public Boolean inStock;
public LocalDate releaseDate;
public Product() {} // Required no‑arg constructor
}
读取与写入
// 读取 Excel
List products = Sheetz.read("products.xlsx", Product.class);
// 读取 CSV
List productsCsv = Sheetz.read("products.csv", Product.class);
// 没有模型?读取为映射
List<Map<String, Object>> data = Sheetz.readMaps("products.xlsx");
// 写入 Excel
Sheetz.write(products, "output.xlsx");
// 写入 CSV
Sheetz.write(products, "output.csv");
流式处理 – 常量内存
处理包含 1 百万行 的文件?使用 stream(),内存保持在约 10 MB,文件大小如何都不受影响。
// Process row‑by‑row – constant memory
Sheetz.stream("huge-file.xlsx", Product.class)
.forEach(product -> process(product));
// Process in batches – perfect for bulk DB inserts
Sheetz.stream("huge-file.xlsx", Product.class)
.batch(1000)
.forEach(batch -> database.bulkInsert(batch));
// Full Java Streams support
long count = Sheetz.stream("huge-file.xlsx", Product.class)
.stream()
.filter(p -> p.price > 100)
.count();
⚠️ 经验法则: 对于超过 100 K 行 的文件,始终使用
stream()。在百万行文件上使用read()加载全部内容会很快触发OutOfMemoryError。
@Column – 灵活映射
标题与字段名不匹配?列顺序奇怪?需要为空单元格提供默认值?@Column 全面搞定。
public class Product {
@Column("Product Name") // Map to a different header
public String name;
@Column(index = 1) // Map by column index (0‑based)
public Double price;
@Column(required = true) // Fail validation if empty
public String sku;
@Column(defaultValue = "pending") // Default for empty cells
public String status;
@Column(format = "dd/MM/yyyy") // Custom date format
public LocalDate orderDate;
@Column(converter = MoneyConverter.class) // Custom converter
public BigDecimal amount;
@Column(ignore = true) // Skip this field entirely
public String internalId;
@Column(width = 20) // Column width in chars (write‑only)
public String description;
}
带丰富错误详情的验证
ValidationResult result = Sheetz.validate("products.csv", Product.class);
System.out.println("Valid rows: " + result.validCount());
System.out.println("Errors: " + result.errorCount());
System.out.println("Success rate: " + result.successRate() + "%");
for (ValidationResult.RowError error : result.errors()) {
System.out.println("Row " + error.row() +
", Col '" + error.column() +
"': " + error.message());
}
// Clean rows only
List validProducts = result.validRows();
流畅构建器 – 完全控制
// Reader Builder
List products = Sheetz.reader(Product.class)
.file("products.xlsx")
.sheet("Inventory") // By name
.headerRow(1) // Header on row 2 (0‑based)
.delimiter(';') // For semicolon‑delimited CSVs
.read();
// Writer Builder
Sheetz.writer(Product.class)
.data(products)
.file("output.xlsx")
.sheet("Products")
.autoSize(true) // Auto‑fit column widths
.freezeHeader(true) // Freeze the header row
.write();
多工作表工作簿
Sheetz.workbook()
.sheet("Products", products)
.sheet("Employees", employees)
.sheet("Orders", orders)
.write("report.xlsx");
自定义转换器示例
public class MoneyConverter implements Converter {
@Override
public BigDecimal fromCell(Object value, ConvertContext ctx) {
String str = value.toString()
.replace("$", "")
.replace(",", "")
.trim();
return new BigDecimal(str);
}
@Override
public Object toCell(BigDecimal value) {
return "$" + value.setScale(2, RoundingMode.HALF_UP);
}
}
通过注解对单个字段使用
@Column(converter = MoneyConverter.class)
public BigDecimal price;
或全局注册以用于所有 BigDecimal 字段
Sheetz.register(BigDecimal.class, new MoneyConverter());
Source: …
支持的类型及示例值
| 类型 | 示例值 |
|---|---|
| String | 任意文本 |
| Integer, Long, Double, Float | 42, 3.14 |
| BigDecimal, BigInteger | 99.99, 999999999 |
| Boolean | true, yes, y, 1, on (不区分大小写) |
| LocalDate, LocalDateTime | 2024-01-15, 2024-01-15 10:30:00 |
| ZonedDateTime, Instant | 2024-01-15T10:30:00Z |
| UUID | 550e8400-e29b-41d4-a716-446655440000 |
| Enum | ACTIVE, active (不区分大小写) |
格式支持
| 格式 | 读取 | 写入 | 流式 |
|---|---|---|---|
.xlsx (Excel 2007+) | ✅ | ✅ | ✅ SAX / SXSSF |
.xls (Excel 97‑2003) | ✅ | ✅ | ❌ |
.csv | ✅ | ✅ | ✅ Buffered |
全局配置
想要在整个应用中更改默认日期格式或 CSV 编码吗?创建一个单独的配置对象并全局应用:
SheetzConfig config = SheetzConfig.builder()
.dateFormat("dd/MM/yyyy")
.dateTimeFormat("dd/MM/yyyy HH:mm")
.trimValues(true)
.skipEmptyRows(true)
.streamingThreshold(10_000) // Auto‑stream above this row count
.charset(StandardCharsets.ISO_8859_1)
.build();
Sheetz.configure(config);
入门
git clone https://github.com/chitralabs/sheetz.git
cd sheetz
mvn clean install
要求
- Java 11+
- Apache POI 5.2.5
- OpenCSV 5.9
许可证: Apache 2.0
基准测试与示例
- 基准测试 –
sheetz-benchmarks仓库包含与 Apache POI、EasyExcel、FastExcel 和 Poiji 的并排 JMH 性能比较,提供完整源码,您可以自行运行。 - 示例 –
sheetz-examples仓库提供 8 个可运行的演示,覆盖端到端的使用案例。
贡献
Sheetz 刚刚发布,正在积极寻找贡献者、问题和反馈。如果你曾经想要一种无需一周 POI 设置就能直接使用的 Excel/CSV 处理工具,试一试吧,如果觉得有用请点个 ⭐。
👉 GitHub: https://github.com/chitralabs/sheetz
讨论
你目前在 Java 中用于 Excel 或 CSV 处理的首选库是什么?请在评论中告诉我——我想了解社区是如何解决这个痛点的!