2026年传感器技术、自动化与智能制造国际会议 (STAIM 2026)
2026/6/25 23:14:48
Java 读取 Excel 文件核心依赖Apache POI(兼容.xls(Excel 97-2003)和.xlsx(Excel 2007+))或EasyExcel(阿里开源,低内存、高性能),以下是两种主流方案的完整实现,覆盖「读取简单单元格、读取指定sheet、读取表头+数据」等场景。
Maven 依赖(需同时引入poi和poi-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>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>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"";}}}// 读取指定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);}EasyExcel 无需加载整个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;}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;}}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);}}FileNotFoundException);chmod 755)。.xls(HSSFWorkbook)最大支持65536行,.xlsx(XSSFWorkbook)无行数限制;SXSSFWorkbook(流式读取);DateUtil.isCellDateFormatted);@ExcelProperty(converter = DateConverter.class)自定义格式转换。| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Apache POI | 功能全、兼容所有Excel特性 | 大数据量易内存溢出、代码繁琐 | 小数据量、需操作复杂Excel(公式/宏) |
| EasyExcel | 低内存、代码简洁、高性能 | 不支持宏/复杂公式 | 大数据量、普通数据读取(推荐) |
FileNotFoundExceptionSXSSFWorkbook流式读取;DateUtil.isCellDateFormatted判断并转换;核心原则:小数据量/复杂Excel用 Apache POI,大数据量/普通读取用 EasyExcel;读取时务必处理空单元格和格式转换,避免空指针/格式错误。