C#使用FileStream与StreamReader读取CSV/XLS多工作表方法
问题核心说明
你当前使用FileStream+StreamReader逐行读取文本的逻辑,仅支持纯文本CSV格式文件,而CSV格式本身是不支持多工作表结构的。你所说的包含多个工作表的文件属于Excel格式(.xls/.xlsx),这类文件是结构化二进制存储格式,不是逐行排列的纯文本,用文本读取的方式根本无法识别工作表边界,硬读只会得到乱码,不存在在原有StreamReader代码基础上小改实现跳转工作表的可能。
实现方案
要读取多工作表Excel文件,需要替换原有纯文本读取逻辑,使用专门处理Excel格式的开源库实现,不需要本地安装Office环境,推荐使用NPOI(同时兼容.xls和.xlsx格式),具体步骤如下:
- 首先在项目中通过Nuget安装NPOI包,执行安装命令:
Install-Package NPOI - 替换原有文件读取代码,支持遍历所有工作表、按名称/索引跳转指定工作表,参考实现如下:
using NPOI.SS.UserModel; using NPOI.HSSF.UserModel; using NPOI.XSSF.UserModel; // 加载Excel文件到工作簿对象 IWorkbook workbook; using (var fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read, FileShare.None)) { switch (fi.Extension.ToLower()) { case ".xls": workbook = new HSSFWorkbook(fs); break; case ".xlsx": workbook = new XSSFWorkbook(fs); break; default: throw new InvalidOperationException("多工作表结构仅存在于xls/xlsx格式Excel文件中,CSV格式不支持该特性"); } } // 用法1:遍历文件内所有工作表 for (int i = 0; i < workbook.NumberOfSheets; i++) { ISheet currentSheet = workbook.GetSheetAt(i); string sheetName = currentSheet.SheetName; // 获取当前工作表名称 // 读取表头(第一行) IRow headerRow = currentSheet.GetRow(0); List<string> headers = new List<string>(); if (headerRow != null) { for (int col = 0; col < headerRow.LastCellNum; col++) { headers.Add(headerRow.GetCell(col)?.ToString() ?? string.Empty); } } // 逐行读取工作表数据(从第二行开始) for (int rowNum = 1; rowNum <= currentSheet.LastRowNum; rowNum++) { IRow currentRow = currentSheet.GetRow(rowNum); if (currentRow == null) continue; // 在此处编写行数据处理逻辑,和你原有逐行处理的逻辑对齐 } } // 用法2:直接跳转到指定工作表 // 按工作表名称跳转 ISheet targetSheet1 = workbook.GetSheet("目标工作表名称"); // 按工作表索引跳转(索引从0开始) ISheet targetSheet2 = workbook.GetSheetAt(1); // 跳转到第二个工作表 if (targetSheet1 != null) { // 读取表头、逐行处理数据的逻辑和上述遍历逻辑一致 }
补充说明
如果你坚持要使用原有StreamReader的文本读取逻辑,只能先把Excel文件内的每个工作表单独导出为独立的CSV文件,此时每个CSV文件对应单张工作表,原有代码不需要修改即可正常运行,但无法在单个CSV文件内实现多工作表跳转。
内容的提问来源于stack exchange,提问作者Anthony Cuartero
相关产品推荐
相关产品推荐

