news 2026/4/15 23:13:20

Java 读取 Excel 文件

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 读取 Excel 文件

Java 读取 Excel 文件

      • 一、前置准备:引入依赖
        • 方案 1:Apache POI(功能全,兼容所有Excel版本)
        • 方案 2:EasyExcel(阿里开源,低内存,推荐大数据量)
      • 二、方案 1:Apache POI 读取 Excel(通用场景)
        • 场景 1:读取所有sheet的所有单元格(基础版)
        • 场景 2:读取指定sheet和指定行(精准读取)
      • 三、方案 2:EasyExcel 读取 Excel(高性能,推荐大数据量)
        • 步骤 1:定义数据实体(与Excel表头映射)
        • 步骤 2:自定义监听器(处理读取到的数据)
        • 步骤 3:读取Excel文件(核心代码)
      • 四、关键注意事项
        • 1. 文件路径与权限
        • 2. 版本兼容
        • 3. 性能优化
        • 4. 日期/数字格式
      • 五、两种方案对比
      • 六、常见问题解决
        • 1. `FileNotFoundException`
        • 2. 内存溢出(OOM)
        • 3. 日期读取为数字

Java 读取 Excel 文件核心依赖Apache POI(兼容.xls(Excel 97-2003)和.xlsx(Excel 2007+))或EasyExcel(阿里开源,低内存、高性能),以下是两种主流方案的完整实现,覆盖「读取简单单元格、读取指定sheet、读取表头+数据」等场景。

一、前置准备:引入依赖

方案 1:Apache POI(功能全,兼容所有Excel版本)

Maven 依赖(需同时引入poipoi-ooxml,分别对应.xls.xlsx):

<dependencies><!-- 核心依赖:处理 .xls --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.5</version><!-- 推荐最新稳定版 --></dependency><!-- 处理 .xlsx --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.5</version></dependency><!-- 可选:简化日期格式处理 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.1.2</version></dependency></dependencies>
方案 2:EasyExcel(阿里开源,低内存,推荐大数据量)

Maven 依赖(仅需核心包,自动兼容.xls/.xlsx):

<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.2</version><!-- 最新版 --></dependency><!-- 可选:日志依赖(EasyExcel 依赖 slf4j) --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>2.0.9</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>2.0.9</version></dependency>

二、方案 1:Apache POI 读取 Excel(通用场景)

场景 1:读取所有sheet的所有单元格(基础版)
importorg.apache.poi.ss.usermodel.*;importorg.apache.poi.xssf.usermodel.XSSFWorkbook;importorg.apache.poi.hssf.usermodel.HSSFWorkbook;importjava.io.FileInputStream;importjava.io.IOException;publicclassPOIExcelReader{publicstaticvoidmain(String[]args){StringfilePath="D:/test.xlsx";// 替换为你的Excel文件路径// 区分 .xls 和 .xlsxWorkbookworkbook=null;try(FileInputStreamfis=newFileInputStream(filePath)){if(filePath.endsWith(".xlsx")){workbook=newXSSFWorkbook(fis);// .xlsx}elseif(filePath.endsWith(".xls")){workbook=newHSSFWorkbook(fis);// .xls}else{thrownewIllegalArgumentException("不支持的Excel格式");}// 遍历所有sheetfor(Sheetsheet:workbook){System.out.println("===== Sheet名称:"+sheet.getSheetName()+" =====");// 遍历所有行(跳过表头:从第1行开始,rowNum=1)for(Rowrow:sheet){// 遍历该行所有单元格for(Cellcell:row){// 获取单元格值(统一格式)StringcellValue=getCellValue(cell);System.out.print(cellValue+"\t");}System.out.println();// 换行}}}catch(IOExceptione){e.printStackTrace();}finally{if(workbook!=null){try{workbook.close();}catch(IOExceptione){e.printStackTrace();}}}}// 工具方法:统一处理不同类型的单元格值privatestaticStringgetCellValue(Cellcell){if(cell==null){return"";}switch(cell.getCellType()){caseSTRING:// 字符串returncell.getStringCellValue();caseNUMERIC:// 数字/日期if(DateUtil.isCellDateFormatted(cell)){// 日期类型returncell.getDateCellValue().toString();}else{// 数字类型(避免科学计数法)returnString.valueOf(cell.getNumericCellValue());}caseBOOLEAN:// 布尔值returnString.valueOf(cell.getBooleanCellValue());caseFORMULA:// 公式returncell.getCellFormula()+" = "+cell.getCachedFormulaResultType();caseBLANK:// 空单元格return"";default:return"";}}}
场景 2:读取指定sheet和指定行(精准读取)
// 读取指定sheet(索引从0开始,或按名称)Sheetsheet=workbook.getSheetAt(0);// 第一个sheet// 或 Sheet sheet = workbook.getSheet("用户数据"); // 按名称// 读取指定行(如第2行,rowNum=1)RowtargetRow=sheet.getRow(1);if(targetRow!=null){// 读取指定单元格(如第3列,cellNum=2)CelltargetCell=targetRow.getCell(2);Stringvalue=getCellValue(targetCell);System.out.println("指定单元格值:"+value);}// 遍历有效行(跳过空行)intlastRowNum=sheet.getLastRowNum();// 最后一行索引for(introwNum=1;rowNum<=lastRowNum;rowNum++){Rowrow=sheet.getRow(rowNum);if(row==null){continue;// 跳过空行}// 读取该行单元格Stringname=getCellValue(row.getCell(0));// 第1列:姓名Stringage=getCellValue(row.getCell(1));// 第2列:年龄System.out.println("姓名:"+name+",年龄:"+age);}

三、方案 2:EasyExcel 读取 Excel(高性能,推荐大数据量)

EasyExcel 无需加载整个Excel到内存,适合读取十万级以上数据,核心是通过「监听器」逐行读取。

步骤 1:定义数据实体(与Excel表头映射)
importcom.alibaba.excel.annotation.ExcelProperty;importlombok.Data;// 对应Excel的表头:姓名、年龄、手机号@Data// Lombok注解,自动生成get/setpublicclassUserExcelDTO{// value:Excel表头名称,index:列索引(可选)@ExcelProperty(value="姓名",index=0)privateStringname;@ExcelProperty(value="年龄",index=1)privateIntegerage;@ExcelProperty(value="手机号",index=2)privateStringphone;}
步骤 2:自定义监听器(处理读取到的数据)
importcom.alibaba.excel.context.AnalysisContext;importcom.alibaba.excel.event.AnalysisEventListener;importjava.util.ArrayList;importjava.util.List;// 自定义监听器,逐行读取数据并存储publicclassUserExcelListenerextendsAnalysisEventListener<UserExcelDTO>{// 存储读取到的数据privateList<UserExcelDTO>dataList=newArrayList<>();// 每读取一行数据触发@Overridepublicvoidinvoke(UserExcelDTOuser,AnalysisContextcontext){dataList.add(user);System.out.println("读取到数据:"+user);// 可在此处批量处理(如每1000条插入数据库)if(dataList.size()>=1000){handleData();// 处理数据dataList.clear();// 清空}}// 所有数据读取完成后触发@OverridepublicvoiddoAfterAllAnalysed(AnalysisContextcontext){handleData();// 处理剩余数据System.out.println("Excel读取完成,总数据量:"+dataList.size());}// 数据处理逻辑(如插入数据库)privatevoidhandleData(){if(!dataList.isEmpty()){// TODO: 批量插入数据库/业务处理System.out.println("批量处理"+dataList.size()+"条数据");}}// 获取读取到的所有数据publicList<UserExcelDTO>getDataList(){returndataList;}}
步骤 3:读取Excel文件(核心代码)
importcom.alibaba.excel.EasyExcel;importjava.util.List;publicclassEasyExcelReader{publicstaticvoidmain(String[]args){StringfilePath="D:/test.xlsx";// 初始化监听器UserExcelListenerlistener=newUserExcelListener();// 读取Excel(指定文件路径、实体类、监听器)EasyExcel.read(filePath,UserExcelDTO.class,listener).sheet("用户数据")// 指定sheet名称(可选,默认第一个).headRowNumber(1)// 表头行数(默认1行).doRead();// 执行读取// 获取所有数据List<UserExcelDTO>dataList=listener.getDataList();System.out.println("最终读取到的数据:"+dataList);}}

四、关键注意事项

1. 文件路径与权限
  • 确保文件路径无中文/空格(避免FileNotFoundException);
  • 若读取服务器文件,需保证Java进程有文件读取权限(如Linux下chmod 755)。
2. 版本兼容
  • .xls(HSSFWorkbook)最大支持65536行,.xlsx(XSSFWorkbook)无行数限制;
  • EasyExcel 自动兼容两种格式,无需手动区分。
3. 性能优化
  • Apache POI 读取大数据量Excel易内存溢出,需用SXSSFWorkbook(流式读取);
  • EasyExcel 天生适合大数据量,无需额外配置。
4. 日期/数字格式
  • Apache POI 需手动判断日期格式(DateUtil.isCellDateFormatted);
  • EasyExcel 可通过@ExcelProperty(converter = DateConverter.class)自定义格式转换。

五、两种方案对比

方案优点缺点适用场景
Apache POI功能全、兼容所有Excel特性大数据量易内存溢出、代码繁琐小数据量、需操作复杂Excel(公式/宏)
EasyExcel低内存、代码简洁、高性能不支持宏/复杂公式大数据量、普通数据读取(推荐)

六、常见问题解决

1.FileNotFoundException
  • 检查文件路径是否正确(绝对路径/相对路径);
  • 检查文件是否被占用(如Excel未关闭)。
2. 内存溢出(OOM)
  • Apache POI:改用SXSSFWorkbook流式读取;
  • 优先使用 EasyExcel。
3. 日期读取为数字
  • Apache POI:通过DateUtil.isCellDateFormatted判断并转换;
  • EasyExcel:配置日期转换器。

核心原则:小数据量/复杂Excel用 Apache POI,大数据量/普通读取用 EasyExcel;读取时务必处理空单元格和格式转换,避免空指针/格式错误。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 3:28:49

从 paperxie 到多工具矩阵:AI 毕业论文写作工具的 “差异化辅助” 指南

毕业论文写作的 “痛点” 从来不是 “写不出文字”&#xff0c;而是选题的精准性、文献的匹配度、逻辑的严谨性、格式的规范性等环节的 “效率与质量平衡”。随着 AI 工具的迭代&#xff0c;单一工具已难以覆盖全流程需求 —— 从 paperxie 的 “流程化引导”&#xff0c;到其他…

作者头像 李华
网站建设 2026/4/9 0:31:49

Hazelcast Kafka集成:3大核心优势与实战部署指南

Hazelcast Kafka集成&#xff1a;3大核心优势与实战部署指南 【免费下载链接】hazelcast hazelcast - 这是一个分布式数据存储和计算平台&#xff0c;用于构建高性能、可扩展的应用程序。适用于实时数据处理、缓存、分布式计算等场景。特点包括高性能、可扩展 项目地址: http…

作者头像 李华
网站建设 2026/4/16 13:35:05

Origin科研绘图——双分组柱状图

更多免费教程和软件 : 双分组柱状图 双分组带误差棒柱状图(Grouped Bar Chart with Error Bars),常用于展示多个类别间在不同实验条件或处理组之间的数值差异。它通过清晰的布局、颜色区分和误差信息示意,使数据表达更加完整和可解释。 效果图 ⭐ 图的特点概述 1. 数据…

作者头像 李华
网站建设 2026/4/16 10:12:38

74、Sendmail 配置宏与特性全解析

Sendmail 配置宏与特性全解析 在邮件服务器配置中,sendmail 是一款功能强大且广泛使用的邮件传输代理。为了实现灵活的配置,sendmail 提供了丰富的 m4 宏,这些宏可以帮助我们根据不同的需求定制邮件服务器的行为。本文将详细介绍 sendmail 中常用的 m4 宏,包括 FEATURE 宏…

作者头像 李华
网站建设 2026/4/16 14:01:17

优测平台如何助力高并发系统全链路压测与瓶颈定位

核心观点摘要 高并发系统稳定性挑战日益严峻&#xff0c;全链路压测成为保障系统性能的关键手段&#xff0c;行业普遍面临压测成本高、瓶颈定位难等问题。 压测工具与平台正朝SaaS化、智能化方向发展&#xff0c;支持在线协作、实时分析与自动化报告生成&#xff0c;显著降低使…

作者头像 李华
网站建设 2026/4/6 3:51:27

76、邮件与Web服务器配置全解析

邮件与Web服务器配置全解析 1. sendmail相关配置 sendmail有众多配置选项和功能,下面为大家详细介绍。 1.1 sendmail配置选项 TryNullMXList :直接连接将本地系统列为最优先MX服务器的远程主机,如同远程主机没有MX记录一样。不过不建议使用此选项。 UnixFromLine=from…

作者头像 李华