跳转至

Java读取Excel文件:从基础到最佳实践

简介

在Java开发中,读取Excel文件是一项常见的任务。无论是处理业务数据、导入配置信息还是进行数据分析,能够有效地读取Excel文件都至关重要。本文将深入探讨Java读取Excel文件的相关知识,涵盖基础概念、使用方法、常见实践以及最佳实践,帮助读者掌握这一重要技能。

目录

  1. 基础概念
    • Excel文件格式
    • Java操作Excel的常用库
  2. 使用方法
    • 使用Apache POI读取Excel文件
    • 使用EasyExcel读取Excel文件
  3. 常见实践
    • 读取不同版本Excel文件
    • 处理复杂Excel结构
    • 数据转换与验证
  4. 最佳实践
    • 性能优化
    • 错误处理与日志记录
    • 代码结构与可维护性
  5. 小结
  6. 参考资料

基础概念

Excel文件格式

Excel文件主要有两种常见格式: - .xls:Excel 97-2003 二进制文件格式,最大行数为65,536行,最大列数为256列。 - .xlsx:Excel 2007及更高版本的Office Open XML格式,理论上行数和列数限制大大提高(行数约1048576行,列数约16384列)。

Java操作Excel的常用库

  • Apache POI:一个开源的Java库,提供了一组API来操作各种Microsoft Office格式文件,包括Excel。支持xls和xlsx格式,功能强大但相对复杂。
  • EasyExcel:阿里巴巴开源的轻量级Java Excel处理框架,基于POI封装,使用简单,性能较好,特别适合处理大数据量的Excel文件。

使用方法

使用Apache POI读取Excel文件

  1. 添加依赖pom.xml中添加Apache POI依赖:
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.0.0</version>
</dependency>
  1. 读取Excel文件示例代码
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class ApachePOIExample {
    public static void main(String[] args) {
        String filePath = "path/to/your/excelFile.xlsx";
        try (FileInputStream fis = new FileInputStream(new File(filePath));
             Workbook workbook = new XSSFWorkbook(fis)) {

            Sheet sheet = workbook.getSheetAt(0);
            for (Row row : sheet) {
                for (Cell cell : row) {
                    String cellValue = getCellValue(cell);
                    System.out.print(cellValue + "\t");
                }
                System.out.println();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static String getCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    return String.valueOf(cell.getNumericCellValue());
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            default:
                return "";
        }
    }
}

使用EasyExcel读取Excel文件

  1. 添加依赖pom.xml中添加EasyExcel依赖:
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.1</version>
</dependency>
  1. 定义数据模型类
import com.alibaba.excel.annotation.ExcelProperty;

public class ExcelData {
    @ExcelProperty("列1")
    private String column1;

    @ExcelProperty("列2")
    private String column2;

    // getters and setters
    public String getColumn1() {
        return column1;
    }

    public void setColumn1(String column1) {
        this.column1 = column1;
    }

    public String getColumn2() {
        return column2;
    }

    public void setColumn2(String column2) {
        this.column2 = column2;
    }
}
  1. 读取Excel文件示例代码
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;

import java.util.List;

public class EasyExcelExample {
    public static void main(String[] args) {
        String filePath = "path/to/your/excelFile.xlsx";
        EasyExcel.read(filePath, ExcelData.class, new ReadListener<ExcelData>() {
            @Override
            public void invoke(ExcelData data, AnalysisContext context) {
                System.out.println(data.getColumn1() + "\t" + data.getColumn2());
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                System.out.println("读取完成");
            }
        }).sheet().doRead();
    }
}

常见实践

读取不同版本Excel文件

使用Apache POI时,根据文件扩展名判断文件格式:

Workbook workbook;
if (filePath.endsWith(".xls")) {
    workbook = new HSSFWorkbook(new FileInputStream(file));
} else if (filePath.endsWith(".xlsx")) {
    workbook = new XSSFWorkbook(new FileInputStream(file));
}

处理复杂Excel结构

对于包含合并单元格、多表头的复杂Excel结构,需要额外处理: - 合并单元格处理

for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
    CellRangeAddress range = sheet.getMergedRegion(i);
    // 处理合并单元格逻辑
}
  • 多表头处理:可以通过自定义数据模型和解析逻辑来处理。

数据转换与验证

读取数据后,根据业务需求进行数据转换和验证:

try {
    int value = Integer.parseInt(cellValue);
    // 验证逻辑
} catch (NumberFormatException e) {
    // 处理转换失败情况
}

最佳实践

性能优化

  • 大数据量处理:使用EasyExcel的事件驱动模式,避免一次性加载整个Excel文件到内存。
  • 减少对象创建:避免在循环中频繁创建不必要的对象。

错误处理与日志记录

  • 详细日志记录:记录读取过程中的错误信息,便于排查问题。
try {
    // 读取Excel文件代码
} catch (IOException e) {
    log.error("读取Excel文件失败", e);
}
  • 优雅的错误提示:向用户提供友好的错误提示信息。

代码结构与可维护性

  • 模块化代码:将读取Excel文件的逻辑封装成独立的方法或类,提高代码的可维护性和复用性。
  • 配置化处理:将文件路径、数据模型等配置信息抽取到配置文件中,便于修改和管理。

小结

本文详细介绍了Java读取Excel文件的相关知识,包括基础概念、使用方法、常见实践和最佳实践。通过使用Apache POI和EasyExcel等库,读者可以根据具体需求选择合适的方式读取Excel文件,并在实际应用中优化性能、处理错误和提高代码质量。

参考资料