跳至页脚内容
USING IRONXL

如何在 C# 中读取 Excel 文件而不是使用 StreamReader

许多C#开发人员在处理Excel文件时遇到一个令人沮丧的挑战:处理文本文件的StreamReader类,在指向Excel文档时完全失败。 如果您尝试使用C#中的StreamReader读取Excel文件而只看到乱码、二进制噪声或意外异常,那么有许多同行也遇到了同样的情况。 本指南详细说明了为什么StreamReader无法处理Excel文件,并向您展示了如何使用IronXL正确解决该问题 -- 这是一个专为.NET设计的Excel库,不需要Excel安装。

混淆通常源于CSV文件 -- 可以用Excel打开和保存 -- 可以与StreamReader一起正常工作。 真正的 Excel 文件(XLSX、XLS、XLSM)需要采用完全不同的方法。 理解这一区别将为您节省数小时的调试时间,并引导您找到完成这项工作的正确工具。

在C#中使用StreamReader读取Excel文件的替代方法 - IronXL:图像1 - IronXL

为什么 StreamReader 无法读取 Excel 文件?

StreamReader是一个基于文本的阅读器。 它使用指定的编码(UTF-8、ASCII 等)逐行读取字符数据,并且不了解二进制结构或压缩存档。 官方的.NET StreamReader 文档证实,此类专为字符编码文本而设计。 Excel文件,尽管看起来像简单的电子表格,实际上是复杂的二进制或ZIP压缩的XML结构,StreamReader无法解释。

当您用StreamReader打开XLSX文件时,实际上是在尝试将ZIP存档作为纯文本读取。 结果得到的不是电子表格数据,而是一串二进制噪声。

// This code will NOT work -- demonstrates the problem
using StreamReader reader = new StreamReader("ProductData.xlsx");
string content = reader.ReadLine();
Console.WriteLine(content); // Outputs garbled binary data like "PK♥♦"
// This code will NOT work -- demonstrates the problem
using StreamReader reader = new StreamReader("ProductData.xlsx");
string content = reader.ReadLine();
Console.WriteLine(content); // Outputs garbled binary data like "PK♥♦"
Imports System.IO

' This code will NOT work -- demonstrates the problem
Using reader As New StreamReader("ProductData.xlsx")
    Dim content As String = reader.ReadLine()
    Console.WriteLine(content) ' Outputs garbled binary data like "PK♥♦"
End Using
$vbLabelText   $csharpLabel

当您运行此代码段时,您会遇到如PK♥♦之类的二进制字符或类似的噪声,而不是看到您的电子表格行。这是因为:

  • XLSX 文件是包含多个 XML 文件的 ZIP 压缩包:工作表、样式、共享字符串、关系。 Open XML SDK 文档提供了该结构的详细说明。
  • XLS 文件使用专有的二进制格式(BIFF——二进制交换文件格式)
  • StreamReader对其读取的字节应用字符编码,产生在这两种格式下均无意义的输出

示例输入

在C#中使用StreamReader读取Excel文件的替代方法 - IronXL:图像2 - Excel输入

使用 StreamReader 时输出乱码

在C#中使用StreamReader读取Excel文件的替代方法 - IronXL:图像3 - 控制台输出

为什么 CSV 格式可以运行而 XLSX 格式不行

CSV(逗号分隔值)是一种纯文本格式。 每一行代表一行文本,每一列之间用逗号分隔。 StreamReader读取CSV文件没有问题,因为它们不包含二进制数据或压缩档案。 XLSX 从根本上来说有所不同:它将多个 XML 文档打包到一个 ZIP 容器中,其中包含元数据、主题和样式定义。 不可能逐行阅读。

在选择工具时,这种区别很重要。 对于CSV文件,File.ReadAllLines是完全适用的。 对于真正的 Excel 工作簿,你需要一个能够从结构层面理解其格式的库。

如何在.NET项目中安装IronXL ?

IronXL是一个.NET库,无需安装 Microsoft Excel 即可读取、写入和创建 Excel 文件。 它支持 XLSX、XLS、XLSM、CSV 和 TSV 格式,并且可以在 Windows、Linux、macOS 和 Docker 容器上运行。

要安装IronXL,可以使用NuGet包管理器控制台或.NET CLI。 该软件包已发布在NuGet上,名称为IronXL

:ProductInstall
dotnet add package IronXL
:ProductInstall
dotnet add package IronXL
SHELL

安装后,向您的文件添加using IronXL;指令,您就可以开始处理Excel文档。

在C#中使用StreamReader读取Excel文件的替代方法 - IronXL:图像5 - 安装

有关详细的安装步骤和NuGet配置选项,请参阅IronXL NuGet安装指南。 我们提供免费试用许可证,您可以在购买前在您的项目中评估IronXL 的效果。

在C#中使用StreamReader读取Excel文件的替代方法 - IronXL:图像4 - 跨平台

如何使用IronXL读取 Excel 文件?

IronXL提供了一个直观的 API,用于在 C# 中读取 Excel 文件。 与StreamReader不同,IronXL理解Excel的内部结构,并为您提供对行、列和单元格值的清晰访问。 IronXL文档提供了所有受支持操作的完整 API 参考。

以下是如何使用IronXL和顶级语句读取 Excel 文件

using IronXL;

// Load the Excel file from disk
WorkBook workbook = WorkBook.Load("ProductData.xlsx");
WorkSheet worksheet = workbook.DefaultWorkSheet;

// Read a specific cell by address
string cellValue = worksheet["A1"].StringValue;
Console.WriteLine($"Cell A1 contains: {cellValue}");

// Iterate over a range of cells
foreach (var cell in worksheet["A1:C10"])
{
    Console.WriteLine($"{cell.AddressString}: {cell.Text}");
}

// Read a numeric value
decimal price = worksheet["B2"].DecimalValue;
Console.WriteLine($"Price: {price:C}");
using IronXL;

// Load the Excel file from disk
WorkBook workbook = WorkBook.Load("ProductData.xlsx");
WorkSheet worksheet = workbook.DefaultWorkSheet;

// Read a specific cell by address
string cellValue = worksheet["A1"].StringValue;
Console.WriteLine($"Cell A1 contains: {cellValue}");

// Iterate over a range of cells
foreach (var cell in worksheet["A1:C10"])
{
    Console.WriteLine($"{cell.AddressString}: {cell.Text}");
}

// Read a numeric value
decimal price = worksheet["B2"].DecimalValue;
Console.WriteLine($"Price: {price:C}");
Imports IronXL

' Load the Excel file from disk
Dim workbook As WorkBook = WorkBook.Load("ProductData.xlsx")
Dim worksheet As WorkSheet = workbook.DefaultWorkSheet

' Read a specific cell by address
Dim cellValue As String = worksheet("A1").StringValue
Console.WriteLine($"Cell A1 contains: {cellValue}")

' Iterate over a range of cells
For Each cell In worksheet("A1:C10")
    Console.WriteLine($"{cell.AddressString}: {cell.Text}")
Next

' Read a numeric value
Dim price As Decimal = worksheet("B2").DecimalValue
Console.WriteLine($"Price: {price:C}")
$vbLabelText   $csharpLabel

WorkBook.Load方法自动检测文件格式(XLSX、XLS、XLSM、CSV)并处理所有复杂的解析。 您可以使用标准Excel表示法,如"A1:C10"访问单元格,这使得代码对熟悉电子表格的人立即可读。

访问多个工作表

许多练习册包含不止一张工作表。 IronXL允许您打开和浏览工作簿,并完整列出所有工作表:

using IronXL;

WorkBook workbook = WorkBook.Load("MultiSheet.xlsx");

// List all worksheets
foreach (WorkSheet sheet in workbook.WorkSheets)
{
    Console.WriteLine($"Sheet: {sheet.Name}, Rows: {sheet.RowCount}");
}

// Access a sheet by name
WorkSheet summary = workbook.GetWorkSheet("Summary");
string totalRevenue = summary["B20"].StringValue;
Console.WriteLine($"Total Revenue: {totalRevenue}");

// Access a sheet by index
WorkSheet firstSheet = workbook.WorkSheets[0];
int lastRow = firstSheet.RowCount;
Console.WriteLine($"Last row in first sheet: {lastRow}");
using IronXL;

WorkBook workbook = WorkBook.Load("MultiSheet.xlsx");

// List all worksheets
foreach (WorkSheet sheet in workbook.WorkSheets)
{
    Console.WriteLine($"Sheet: {sheet.Name}, Rows: {sheet.RowCount}");
}

// Access a sheet by name
WorkSheet summary = workbook.GetWorkSheet("Summary");
string totalRevenue = summary["B20"].StringValue;
Console.WriteLine($"Total Revenue: {totalRevenue}");

// Access a sheet by index
WorkSheet firstSheet = workbook.WorkSheets[0];
int lastRow = firstSheet.RowCount;
Console.WriteLine($"Last row in first sheet: {lastRow}");
Imports IronXL

Dim workbook As WorkBook = WorkBook.Load("MultiSheet.xlsx")

' List all worksheets
For Each sheet As WorkSheet In workbook.WorkSheets
    Console.WriteLine($"Sheet: {sheet.Name}, Rows: {sheet.RowCount}")
Next

' Access a sheet by name
Dim summary As WorkSheet = workbook.GetWorkSheet("Summary")
Dim totalRevenue As String = summary("B20").StringValue
Console.WriteLine($"Total Revenue: {totalRevenue}")

' Access a sheet by index
Dim firstSheet As WorkSheet = workbook.WorkSheets(0)
Dim lastRow As Integer = firstSheet.RowCount
Console.WriteLine($"Last row in first sheet: {lastRow}")
$vbLabelText   $csharpLabel

这种方法比任何试图用StreamReader或字符串操作来解析Excel的方法要干净得多。

如何从内存流中读取Excel数据?

实际应用中经常需要处理来自数据流而不是磁盘文件的 Excel 文件。 常见场景包括处理从 Web 表单上传的文件、从数据库 BLOB 列检索工作簿,或处理从云存储(Azure Blob Storage、AWS S3)下载的文件。 IronXL通过WorkBook.FromStream解决这些场景:

using IronXL;
using System.IO;

// Simulate reading file bytes (e.g., from a database or web upload)
byte[] fileBytes = File.ReadAllBytes("ProductData.xlsx");

using MemoryStream stream = new MemoryStream(fileBytes);
WorkBook workbook = WorkBook.FromStream(stream);
WorkSheet worksheet = workbook.DefaultWorkSheet;

// Get row and column counts
Console.WriteLine($"Rows: {worksheet.RowCount}, Columns: {worksheet.ColumnCount}");

// Convert to DataTable for database or grid binding
var dataTable = worksheet.ToDataTable(useHeaderRow: true);
Console.WriteLine($"Loaded {dataTable.Rows.Count} data rows");

foreach (System.Data.DataRow row in dataTable.Rows)
{
    string productName = row["ProductName"]?.ToString() ?? string.Empty;
    string sku = row["SKU"]?.ToString() ?? string.Empty;
    Console.WriteLine($"Product: {productName}, SKU: {sku}");
}
using IronXL;
using System.IO;

// Simulate reading file bytes (e.g., from a database or web upload)
byte[] fileBytes = File.ReadAllBytes("ProductData.xlsx");

using MemoryStream stream = new MemoryStream(fileBytes);
WorkBook workbook = WorkBook.FromStream(stream);
WorkSheet worksheet = workbook.DefaultWorkSheet;

// Get row and column counts
Console.WriteLine($"Rows: {worksheet.RowCount}, Columns: {worksheet.ColumnCount}");

// Convert to DataTable for database or grid binding
var dataTable = worksheet.ToDataTable(useHeaderRow: true);
Console.WriteLine($"Loaded {dataTable.Rows.Count} data rows");

foreach (System.Data.DataRow row in dataTable.Rows)
{
    string productName = row["ProductName"]?.ToString() ?? string.Empty;
    string sku = row["SKU"]?.ToString() ?? string.Empty;
    Console.WriteLine($"Product: {productName}, SKU: {sku}");
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

Stream -- FileStream或网络流。 这种灵活性意味着您无需为了读取 Excel 数据而将临时文件写入磁盘。 转换为SqlBulkCopy、数据绑定控件和报告框架集成。

流处理的输出

在C#中使用StreamReader读取Excel文件的替代方法 - IronXL:图像6 - 从MemoryStream输出读取Excel

何时使用事件驱动型 Excel 读取?

在事件驱动的架构中 -- 例如,Windows Forms中的文件上传按钮或ASP.NET控制器操作 -- 方法签名通常包括EventArgs e参数。 Excel 处理逻辑仍然使用相同的IronXL API,但它是从事件处理程序内部调用的,而不是从顶级语句调用的。 IronXL可以无缝集成到任何事件驱动或异步工作流程中,因为它不依赖于 UI 线程。

在C#中使用StreamReader读取Excel文件的替代方法 - IronXL:图像7 - 功能

如何在Excel和CSV格式之间进行转换?

虽然StreamReader可以处理CSV文件,但生产应用程序通常需要在Excel和CSV之间移动数据。IronXL使得格式转换变得简单。 只需几行代码,即可将 Excel 数据导出为 CSV 文件,或将 CSV 数据导入到工作簿中:

using IronXL;

// Load an Excel file and save as CSV
WorkBook workbook = WorkBook.Load("SalesData.xlsx");
workbook.SaveAsCsv("output.csv");

// Load a CSV file and save as Excel
WorkBook csvWorkbook = WorkBook.LoadCSV("legacy-report.csv");
csvWorkbook.SaveAs("converted.xlsx");

// Export a specific worksheet to CSV
WorkSheet worksheet = workbook.WorkSheets[0];
worksheet.SaveAsCsv("sheet1-export.csv");
using IronXL;

// Load an Excel file and save as CSV
WorkBook workbook = WorkBook.Load("SalesData.xlsx");
workbook.SaveAsCsv("output.csv");

// Load a CSV file and save as Excel
WorkBook csvWorkbook = WorkBook.LoadCSV("legacy-report.csv");
csvWorkbook.SaveAs("converted.xlsx");

// Export a specific worksheet to CSV
WorkSheet worksheet = workbook.WorkSheets[0];
worksheet.SaveAsCsv("sheet1-export.csv");
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

这些转换操作会在更改容器格式的同时保留您的数据。 将 Excel 转换为 CSV 时, IronXL默认导出第一个工作表; 您可以指定任何您选择的图纸。 将 CSV 文件转换为 Excel 文件会创建一个结构正确的 Excel 工作簿,您可以对其进行格式化、添加公式并写入其他数据

格式支持方面有哪些区别?

StreamReader 和IronXL读取不同文件格式的比较
文件格式 StreamReader IronXL 注意事项
CSV(.csv) 纯文本;StreamReader 工作正常
XLSX (.xlsx) ZIP压缩的XML;需要库
XLS(.xls) 二进制 BIFF 格式;需要库
XLSM (.xlsm) 启用宏的工作簿
TSV(.tsv) 制表符分隔的纯文本

如何使用IronXL创建和格式化 Excel 文件?

读取Excel数据只是工作流程的一部分。 许多应用程序还需要创建新的 Excel 文件并应用格式。 IronXL支持单元格格式设置,包括字体、颜色、边框、数字格式和单元格合并

using IronXL;

// Create a new workbook and worksheet
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
WorkSheet sheet = workbook.CreateWorkSheet("Report");

// Write headers with formatting
sheet["A1"].Value = "Product";
sheet["B1"].Value = "Units Sold";
sheet["C1"].Value = "Revenue";

// Apply bold formatting to header row
sheet["A1:C1"].Style.Font.Bold = true;
sheet["A1:C1"].Style.SetBackgroundColor("#4472C4");
sheet["A1:C1"].Style.Font.Color = "#FFFFFF";

// Write data rows
string[] products = { "Widget A", "Widget B", "Widget C" };
int[] units = { 120, 85, 210 };
decimal[] revenues = { 2400.00m, 1700.00m, 4200.00m };

for (int i = 0; i < products.Length; i++)
{
    sheet[$"A{i + 2}"].Value = products[i];
    sheet[$"B{i + 2}"].Value = units[i];
    sheet[$"C{i + 2}"].Value = revenues[i];
    sheet[$"C{i + 2}"].FormatString = "$#,##0.00";
}

// Save the workbook
workbook.SaveAs("FormattedReport.xlsx");
Console.WriteLine("Report created successfully.");
using IronXL;

// Create a new workbook and worksheet
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
WorkSheet sheet = workbook.CreateWorkSheet("Report");

// Write headers with formatting
sheet["A1"].Value = "Product";
sheet["B1"].Value = "Units Sold";
sheet["C1"].Value = "Revenue";

// Apply bold formatting to header row
sheet["A1:C1"].Style.Font.Bold = true;
sheet["A1:C1"].Style.SetBackgroundColor("#4472C4");
sheet["A1:C1"].Style.Font.Color = "#FFFFFF";

// Write data rows
string[] products = { "Widget A", "Widget B", "Widget C" };
int[] units = { 120, 85, 210 };
decimal[] revenues = { 2400.00m, 1700.00m, 4200.00m };

for (int i = 0; i < products.Length; i++)
{
    sheet[$"A{i + 2}"].Value = products[i];
    sheet[$"B{i + 2}"].Value = units[i];
    sheet[$"C{i + 2}"].Value = revenues[i];
    sheet[$"C{i + 2}"].FormatString = "$#,##0.00";
}

// Save the workbook
workbook.SaveAs("FormattedReport.xlsx");
Console.WriteLine("Report created successfully.");
Imports IronXL

' Create a new workbook and worksheet
Dim workbook As WorkBook = WorkBook.Create(ExcelFileFormat.XLSX)
Dim sheet As WorkSheet = workbook.CreateWorkSheet("Report")

' Write headers with formatting
sheet("A1").Value = "Product"
sheet("B1").Value = "Units Sold"
sheet("C1").Value = "Revenue"

' Apply bold formatting to header row
sheet("A1:C1").Style.Font.Bold = True
sheet("A1:C1").Style.SetBackgroundColor("#4472C4")
sheet("A1:C1").Style.Font.Color = "#FFFFFF"

' Write data rows
Dim products As String() = {"Widget A", "Widget B", "Widget C"}
Dim units As Integer() = {120, 85, 210}
Dim revenues As Decimal() = {2400.0D, 1700.0D, 4200.0D}

For i As Integer = 0 To products.Length - 1
    sheet($"A{i + 2}").Value = products(i)
    sheet($"B{i + 2}").Value = units(i)
    sheet($"C{i + 2}").Value = revenues(i)
    sheet($"C{i + 2}").FormatString = "$#,##0.00"
Next

' Save the workbook
workbook.SaveAs("FormattedReport.xlsx")
Console.WriteLine("Report created successfully.")
$vbLabelText   $csharpLabel

IronXL既能读取现有工作簿,又能创建新的格式化文件,使其成为适用于.NET应用程序的完整 Excel 解决方案。 请查看IronXL 的完整功能页面,了解支持的操作的详细信息。

将数据导出为其他格式

IronXL还支持将工作簿数据导出到DataSet 对象,这在将多个工作表加载到内存中进行跨工作表计算或数据库批量插入操作时特别有用。 DataTable

在C#中使用StreamReader读取Excel文件的替代方法 - IronXL:图像8 - 许可

如何在生产环境中获得IronXL 的许可并进行部署?

IronXL 可免费用于开发和测试。 生产应用需要许可证。 您可以访问产品页面了解IronXL 的许可选项,根据您的部署需求,这些选项涵盖开发人员、团队和组织级别。

购买后,请在调用任何IronXL函数之前,在代码中应用您的许可证密钥:

IronXL.License.LicenseKey = "YOUR-LICENSE-KEY-HERE";
IronXL.License.LicenseKey = "YOUR-LICENSE-KEY-HERE";
Imports IronXL

IronXL.License.LicenseKey = "YOUR-LICENSE-KEY-HERE"
$vbLabelText   $csharpLabel

或者,在您的部署环境中设置IRONXL_LICENSE_KEY环境变量,IronXL将自动获取它。 对于容器化部署(Docker、Kubernetes)和云环境,这是首选方法,因为在这些环境中,硬编码密钥是不可接受的。

为了便于评估,免费试用许可证提供完整功能,以便您在购买前验证IronXL是否适用于您的特定工作负载。 无需信用卡即可试用,试用期立即生效。

与 Microsoft.Office.Interop.Excel 等替代方案相比, IronXL具有以下几个部署优势:

  • 服务器上无需安装 Microsoft Excel
  • 兼容 Linux 和 Docker——这对云原生应用至关重要
  • 没有 COM 对象生命周期管理或单元线程问题
  • 服务器环境下启动速度更快,内存占用更低
  • 在所有支持的平台上表现一致

IronXL具备这些特性,对于任何需要在生产环境中处理 Excel 文件的.NET应用程序来说,无论是在本地还是在云端,它都是一个实用的选择。

常见问题解答

为什么 StreamReader 不能直接处理 Excel 文件?

StreamReader 专为读取文本文件而设计,无法解析 Excel 文件中使用的二进制或复杂结构化数据格式。因此,尝试使用 StreamReader 直接读取 Excel 文件时,可能会出现乱码或异常。

在 C# 中读取 Excel 文件,推荐的解决方案是什么?

推荐的解决方案是使用IronXL,IronXL是一个功能强大的库,它允许您在 C# 中读取、编辑和创建 Excel 文件,而无需 Excel Interop。IronXL 可以高效地处理 Excel 文件的复杂结构。

IronXL相较于 Excel Interop 有哪些优势?

IronXL相比 Excel Interop 具有多项优势,包括更好的性能、无需在服务器或客户端计算机上安装 Excel、更容易部署,以及能够在 Web 和云环境中处理 Excel 文件。

IronXL是否能够处理 .xls 和 .xlsx 文件格式?

是的, IronXL能够处理 .xls 和 .xlsx Excel 文件格式,为处理不同类型 Excel 文档的开发人员提供了灵活性。

IronXL可以用于Web应用程序吗?

是的, IronXL 的设计用途广泛,可用于各种应用程序类型,包括 Web 应用程序,这得益于其轻量级特性以及与.NET Core和.NET Framework 的兼容性。

IronXL是否需要安装 Microsoft Excel?

不, IronXL不需要在服务器或客户端计算机上安装 Microsoft Excel,因此非常适合服务器端应用程序和云环境。

IronXL有哪些典型应用场景?

IronXL的典型用例包括从 Excel 文件中提取和分析数据、生成报告、自动创建和修改 Excel 文件以及将 Excel 数据集成到其他应用程序中。

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

钢铁支援团队

我们每周 5 天,每天 24 小时在线。
聊天
电子邮件
打电话给我