跳转至

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文件格式,基于BIFF(二进制文件格式)。 - .xlsx:Excel 2007及更高版本的文件格式,基于Open XML标准,本质上是一个压缩的XML文件集合。

Java操作Excel的库

  • Apache POI:一个开源的Java库,提供了对各种微软Office格式文件的读写支持,包括Excel。它功能强大,支持读取和写入不同版本的Excel文件。
  • EasyExcel:是一个基于Apache POI封装的轻量级Java库,专注于简化Excel操作,尤其在读取和写入大数据量的Excel文件时性能表现出色。

使用方法

使用Apache POI读取Excel文件

  1. 添加依赖 在Maven项目的pom.xml文件中添加以下依赖:
<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/file.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. 添加依赖 在Maven项目的pom.xml文件中添加以下依赖:
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.1</version>
</dependency>
  1. 定义数据模型类
import com.alibaba.excel.annotation.ExcelProperty;

public class User {
    @ExcelProperty("姓名")
    private String name;
    @ExcelProperty("年龄")
    private Integer age;

    // 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;
    }
}
  1. 读取Excel文件示例代码
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;

import java.util.List;

public class EasyExcelExample {
    public static void main(String[] args) {
        String filePath = "path/to/your/file.xlsx";
        EasyExcel.read(filePath, User.class, new UserDataListener()).sheet().doRead();
    }

    private static class UserDataListener extends AnalysisEventListener<User> {
        @Override
        public void onReadData(User user, AnalysisContext context) {
            System.out.println(user.getName() + "\t" + user.getAge());
        }

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

常见实践

读取不同版本的Excel文件

Apache POI可以处理不同版本的Excel文件。对于.xls文件,使用HSSFWorkbook;对于.xlsx文件,使用XSSFWorkbook。例如:

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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 ReadDifferentExcelVersions {
    public static void main(String[] args) {
        String xlsFilePath = "path/to/your/file.xls";
        String xlsxFilePath = "path/to/your/file.xlsx";

        readExcel(xlsFilePath, true);
        readExcel(xlsxFilePath, false);
    }

    private static void readExcel(String filePath, boolean isXls) {
        try (FileInputStream fis = new FileInputStream(new File(filePath));
             Workbook workbook = isXls? new HSSFWorkbook(fis) : 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) {
        // 同前面的getCellValue方法
    }
}

处理Excel中的各种数据类型

Excel中的数据类型包括字符串、数字、日期、布尔值、公式等。在读取时,需要根据单元格的类型进行相应的处理,如前面getCellValue方法中所示。

读取特定单元格或区域的数据

要读取特定单元格的数据,可以通过指定行号和列号来获取单元格。例如:

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 ReadSpecificCell {
    public static void main(String[] args) {
        String filePath = "path/to/your/file.xlsx";
        try (FileInputStream fis = new FileInputStream(new File(filePath));
             Workbook workbook = new XSSFWorkbook(fis)) {

            Sheet sheet = workbook.getSheetAt(0);
            Row row = sheet.getRow(2); // 第三行
            Cell cell = row.getCell(1); // 第二列
            String cellValue = getCellValue(cell);
            System.out.println(cellValue);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static String getCellValue(Cell cell) {
        // 同前面的getCellValue方法
    }
}

要读取特定区域的数据,可以使用循环遍历指定的行和列范围。

最佳实践

性能优化

  • 使用流处理:对于大数据量的Excel文件,使用流处理可以避免一次性将整个文件加载到内存中。EasyExcel在这方面表现出色,它基于事件驱动的方式逐行读取数据。
  • 减少不必要的对象创建:在读取过程中,尽量减少不必要的对象创建,以降低内存消耗。例如,重用已有的对象来存储数据。

错误处理与异常管理

  • 捕获并处理异常:在读取Excel文件时,可能会遇到各种异常,如文件不存在、格式错误等。应该使用try - catch块来捕获并处理这些异常,确保程序的稳定性。
  • 提供详细的错误信息:在捕获异常时,记录详细的错误信息,以便于调试和排查问题。

代码结构与可维护性

  • 模块化代码:将读取Excel文件的逻辑封装到独立的方法或类中,提高代码的可维护性和复用性。
  • 添加注释:在代码中添加清晰的注释,解释关键步骤和逻辑,方便其他开发人员理解和维护代码。

小结

本文详细介绍了Java读取Excel文件的相关知识,包括基础概念、使用方法、常见实践以及最佳实践。通过学习和实践这些内容,读者可以在Java项目中高效地读取Excel文件,并处理各种复杂的业务需求。无论是使用功能强大的Apache POI还是轻量级的EasyExcel,都可以根据项目的具体情况选择合适的库和方法。同时,遵循最佳实践可以提高代码的性能、稳定性和可维护性。

参考资料