首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java高效读取Excel表格数据

Java高效读取Excel表格数据

作者头像
编程小白狼
发布2025-08-30 08:50:35
发布2025-08-30 08:50:35
9400
代码可运行
举报
文章被收录于专栏:编程小白狼编程小白狼
运行总次数:0
代码可运行

在日常开发中,Excel文件读取是一个常见的需求,无论是数据处理、报表分析还是数据导入导出,都需要高效地处理Excel文件。本文将介绍几种Java中高效读取Excel数据的方法,并对比它们的性能特点。

一、常用技术选型

1. Apache POI

Apache POI是Apache软件基金会的开源项目,提供了对Microsoft Office格式文件的读写功能,是Java领域最流行的Excel处理库。

2. EasyExcel

阿里开源的EasyExcel基于POI进行封装优化,解决了POI的内存消耗问题,特别适合大数据量的读取。

二、Apache POI读取方案

1. 依赖引入
代码语言:javascript
代码运行次数:0
运行
复制
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.2.3</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.3</version>
</dependency>
2. 事件模式读取(SAX方式)

对于大型Excel文件,推荐使用事件模式读取,避免内存溢出:

代码语言:javascript
代码运行次数:0
运行
复制
public class ExcelSAXReader {
    public void readExcel(String filePath) {
        try (InputStream is = new FileInputStream(filePath)) {
            Workbook workbook = WorkbookFactory.create(is);
            Sheet sheet = workbook.getSheetAt(0);
            
            // 使用迭代器遍历行
            Iterator<Row> rowIterator = sheet.iterator();
            while (rowIterator.hasNext()) {
                Row row = rowIterator.next();
                processRow(row);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private void processRow(Row row) {
        Iterator<Cell> cellIterator = row.cellIterator();
        while (cellIterator.hasNext()) {
            Cell cell = cellIterator.next();
            System.out.print(getCellValue(cell) + "\t");
        }
        System.out.println();
    }
    
    private String getCellValue(Cell cell) {
        return switch (cell.getCellType()) {
            case STRING -> cell.getStringCellValue();
            case NUMERIC -> 
                DateUtil.isCellDateFormatted(cell) ? 
                cell.getDateCellValue().toString() : 
                String.valueOf(cell.getNumericCellValue());
            case BOOLEAN -> String.valueOf(cell.getBooleanCellValue());
            case FORMULA -> cell.getCellFormula();
            default -> "";
        };
    }
}
3. 流式读取(针对.xlsx格式)

对于超大文件,使用XSSF and SAX方式:

代码语言:javascript
代码运行次数:0
运行
复制
public class ExcelStreamReader {
    public void processLargeExcel(String filename) throws Exception {
        OPCPackage pkg = OPCPackage.open(filename);
        XSSFReader reader = new XSSFReader(pkg);
        SharedStringsTable sst = reader.getSharedStringsTable();
        XMLReader parser = fetchSheetParser(sst);
        
        InputStream sheet2 = reader.getSheet("rId1");
        InputSource sheetSource = new InputSource(sheet2);
        parser.parse(sheetSource);
        sheet2.close();
    }
    
    private XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
        XMLReader parser = XMLReaderFactory.createXMLReader();
        ContentHandler handler = new SheetHandler(sst);
        parser.setContentHandler(handler);
        return parser;
    }
    
    private static class SheetHandler extends DefaultHandler {
        // 实现具体的SAX解析逻辑
    }
}

三、EasyExcel读取方案

1. 引入依赖
代码语言:javascript
代码运行次数:0
运行
复制
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.2</version>
</dependency>
2. 简单读取示例
代码语言:javascript
代码运行次数:0
运行
复制
// 定义数据模型
@Data
public class DemoData {
    @ExcelProperty(index = 0)
    private String name;
    
    @ExcelProperty(index = 1)
    private Integer age;
    
    @ExcelProperty(index = 2)
    private Date birthday;
}

// 读取监听器
public class DemoDataListener extends AnalysisEventListener<DemoData> {
    private static final int BATCH_COUNT = 100;
    private List<DemoData> cachedDataList = new ArrayList<>(BATCH_COUNT);
    
    @Override
    public void invoke(DemoData data, AnalysisContext context) {
        cachedDataList.add(data);
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            cachedDataList = new ArrayList<>(BATCH_COUNT);
        }
    }
    
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        saveData();
    }
    
    private void saveData() {
        // 批量保存数据
        if (!cachedDataList.isEmpty()) {
            // 这里实现数据持久化逻辑
            System.out.println("保存" + cachedDataList.size() + "条数据");
            cachedDataList.clear();
        }
    }
}

// 使用EasyExcel读取
public class EasyExcelReader {
    public void readExcel(String filePath) {
        EasyExcel.read(filePath, DemoData.class, new DemoDataListener())
                .sheet()
                .doRead();
    }
}
3. 复杂读取场景
代码语言:javascript
代码运行次数:0
运行
复制
// 读取多个sheet
EasyExcel.read(filePath)
        .sheet(0)  // 第一个sheet
        .doRead();

EasyExcel.read(filePath)
        .sheet("Sheet1")  // 按名称读取
        .doRead();

// 读取部分列
EasyExcel.read(filePath, DemoData.class, new DemoDataListener())
        .extraRead(CellExtraTypeEnum.COMMENT)  // 读取注释
        .sheet()
        .doRead();

// 自定义转换器
public class CustomConverter implements Converter<String> {
    @Override
    public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
        // 自定义转换逻辑
        return "转换后的数据:" + cellData.getStringValue();
    }
}

四、性能优化建议

1. 内存优化
  • 使用流式读取代替DOM式读取
  • 及时清理不再使用的对象引用
  • 设置合适的JVM内存参数
2. 读取策略优化
  • 按需读取,避免一次性加载全部数据
  • 使用缓存机制减少重复IO操作
  • 批量处理数据,减少数据库操作次数
3. 代码层面优化
代码语言:javascript
代码运行次数:0
运行
复制
// 使用try-with-resources确保资源释放
try (InputStream is = new FileInputStream(file);
     Workbook workbook = WorkbookFactory.create(is)) {
    // 处理逻辑
}

// 避免在循环中创建对象
CellStyle cellStyle = workbook.createCellStyle();
for (Row row : sheet) {
    Cell cell = row.createCell(0);
    cell.setCellStyle(cellStyle);  // 复用样式对象
}

// 使用数据类型检测优化处理逻辑
if (cell.getCellType() == CellType.NUMERIC) {
    if (DateUtil.isCellDateFormatted(cell)) {
        // 处理日期
    } else {
        // 处理数字
    }
}

五、性能对比

方案

内存占用

读取速度

适用场景

POI DOM模式

小文件,需要完整访问

POI SAX模式

大文件,顺序读取

EasyExcel

极低

很快

超大文件,批量处理

六、总结

选择合适的Excel读取方案需要根据具体场景决定:

  • 对于小文件(<10MB),可以使用POI的标准API,代码简单易用
  • 对于中等文件(10-100MB),建议使用POI的流式API
  • 对于大文件(>100MB),强烈推荐使用EasyExcel

无论选择哪种方案,都应该注意资源释放、异常处理和内存管理,确保程序的稳定性和性能。希望本文能帮助你在实际开发中选择合适的Excel读取方案。

注意事项

  1. 处理Excel时注意日期格式的转换问题
  2. 考虑空单元格和异常数据的处理
  3. 注意字符编码问题,特别是中文处理
  4. 大型文件处理时建议添加进度指示器
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-08-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、常用技术选型
    • 1. Apache POI
    • 2. EasyExcel
  • 二、Apache POI读取方案
    • 1. 依赖引入
    • 2. 事件模式读取(SAX方式)
    • 3. 流式读取(针对.xlsx格式)
  • 三、EasyExcel读取方案
    • 1. 引入依赖
    • 2. 简单读取示例
    • 3. 复杂读取场景
  • 四、性能优化建议
    • 1. 内存优化
    • 2. 读取策略优化
    • 3. 代码层面优化
  • 五、性能对比
  • 六、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档