目 录CONTENT

文章目录

CSharp(五十五) 本地数据交互详解 —— 读取各类文件

C# 本地数据交互详解 —— 读取各类文件


一、概述——C# 怎么读写文件?

1.1 C# 文件操作的核心类

所有文件读写都在 System.IO 命名空间下。核心类家族:

用途 特点
File 静态方法,一次性读写 最简单,适合小文件
FileStream 流式读写 灵活,控制每个字节
StreamReader / StreamWriter 读写文本文件 逐行处理,适合大文件
BinaryReader / BinaryWriter 读写二进制文件 按数据类型读取
FileInfo 文件和目录信息 获取大小、日期等属性

1.2 本篇要讲的内容

📝 TXT 文件       → 用 File、StreamReader(C# 自带,不需要装包)
📊 Excel 文件      → 用 ClosedXML(第三方库,NuGet 安装)
💾 二进制文件      → 用 FileStream、BinaryReader(C# 自带)
📄 PDF 文件        → 用 PdfPig 或 iTextSharp(第三方库,NuGet 安装)

二、读取 TXT 文本文件

2.1 准备一个测试文件

先在项目目录下创建一个 data.txt

张三,18,92
李四,19,85
王五,18,76
赵六,20,58
孙七,19,88

2.2 方法一:File.ReadAllText —— 一次性读全部(最简单)

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string path = "data.txt";

        // 检查文件是否存在
        if (!File.Exists(path))
        {
            Console.WriteLine($"文件 {path} 不存在!");
            return;
        }

        // 一次性读取全部内容
        string allText = File.ReadAllText(path);
        Console.WriteLine("===== 文件全部内容 =====");
        Console.WriteLine(allText);
    }
}

输出:

===== 文件全部内容 =====
张三,18,92
李四,19,85
王五,18,76
赵六,20,58
孙七,19,88

2.3 方法二:File.ReadAllLines —— 逐行读取(返回数组)

string[] lines = File.ReadAllLines("data.txt");

Console.WriteLine("===== 逐行读取 =====");
for (int i = 0; i < lines.Length; i++)
{
    Console.WriteLine($"第{i + 1}行: {lines[i]}");

    // 按逗号拆分,解析每列数据
    string[] parts = lines[i].Split(',');
    string name = parts[0];
    int age = int.Parse(parts[1]);
    int score = int.Parse(parts[2]);

    Console.WriteLine($"  → 姓名:{name}, 年龄:{age}, 分数:{score}");
}

输出:

===== 逐行读取 =====
第1行: 张三,18,92
  → 姓名:张三, 年龄:18, 分数:92
第2行: 李四,19,85
  → 姓名:李四, 年龄:19, 分数:85
...

适用场景File.ReadAllLines 适合小文件(几十 MB 以内),一行一个字符串数组,遍历处理很方便。

2.4 方法三:StreamReader —— 逐行读取(适合大文件)

// StreamReader 一次只读一行,内存友好,适合大文件
using (StreamReader reader = new StreamReader("data.txt"))
{
    Console.WriteLine("===== StreamReader 逐行读取 =====");
    string line;
    int lineNum = 0;

    while ((line = reader.ReadLine()) != null)  // 读到 null 表示文件结束
    {
        lineNum++;
        Console.WriteLine($"第{lineNum}行: {line}");
    }

    Console.WriteLine($"共读取 {lineNum} 行");
}

三种读取方式对比:

方式 方法 适用场景 内存占用
File.ReadAllText 一次性读全部文本 小文件(<10MB)
File.ReadAllLines 一次性读全部行 小文件(<50MB) 较大
StreamReader 一行一行读 大文件(几百MB~GB)

2.5 完整示例——读取并解析 CSV 数据

using System;
using System.Collections.Generic;
using System.IO;

public class Student
{
    public string Name;
    public int Age;
    public int Score;
    public override string ToString() => $"{Name,-6} | {Age}岁 | {Score}分";
}

class Program
{
    static void Main()
    {
        Console.WriteLine("===== 读取并解析 data.txt =====\n");

        List<Student> students = new List<Student>();

        using (StreamReader reader = new StreamReader("data.txt"))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                // 跳过空行
                if (string.IsNullOrWhiteSpace(line)) continue;

                string[] parts = line.Split(',');
                if (parts.Length < 3) continue;  // 跳过格式不对的行

                students.Add(new Student
                {
                    Name = parts[0],
                    Age = int.Parse(parts[1]),
                    Score = int.Parse(parts[2])
                });
            }
        }

        Console.WriteLine($"共读取 {students.Count} 条记录\n");

        // 分析数据
        Console.WriteLine("【学生列表】");
        foreach (var s in students)
            Console.WriteLine($"  {s}");

        Console.WriteLine($"\n【统计】");
        Console.WriteLine($"  平均分: {students.Average(s => s.Score):F1}");
        Console.WriteLine($"  最高分: {students.Max(s => s.Score)}");
        Console.WriteLine($"  及格率: {(double)students.Count(s => s.Score >= 60) / students.Count * 100:F1}%");
    }
}

2.6 写入 TXT 文件

// 写入文本
File.WriteAllText("output.txt", "Hello World!这是写入的内容。");

// 写入多行
string[] lines = { "第一行", "第二行", "第三行" };
File.WriteAllLines("output.txt", lines);

// 追加内容(不覆盖原内容)
File.AppendAllText("output.txt", "\n这是追加的一行");

三、读取二进制文件

3.1 什么是二进制文件?

二进制文件就是数据以字节形式直接存储,不是可读的文本。比如:

  • 图片文件(.jpg、.png)
  • 音频文件(.mp3、.wav)
  • 可执行文件(.exe、.dll)
  • 自定义的数据文件

3.2 读取二进制数据 —— FileStream + BinaryReader

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string path = "data.bin";

        // ===== 第一步:写入一个二进制文件(演示用) =====
        using (BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create)))
        {
            writer.Write(42);                    // 写 int
            writer.Write(3.14159);               // 写 double
            writer.Write("Hello Binary!");       // 写 string
            writer.Write(true);                  // 写 bool
            writer.Write(1234567890123L);        // 写 long
        }
        Console.WriteLine("二进制文件已创建");

        // ===== 第二步:读取二进制文件 =====
        using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open)))
        {
            int intValue = reader.ReadInt32();       // 读 int
            double doubleValue = reader.ReadDouble();  // 读 double
            string stringValue = reader.ReadString();  // 读 string
            bool boolValue = reader.ReadBoolean();     // 读 bool
            long longValue = reader.ReadInt64();       // 读 long

            Console.WriteLine($"int: {intValue}");
            Console.WriteLine($"double: {doubleValue}");
            Console.WriteLine($"string: {stringValue}");
            Console.WriteLine($"bool: {boolValue}");
            Console.WriteLine($"long: {longValue}");
        }
    }
}

输出:

二进制文件已创建
int: 42
double: 3.14159
string: Hello Binary!
bool: True
long: 1234567890123

关键规则:二进制文件读的顺序必须和写的顺序完全一致,否则会读到错误的数据!

3.3 按字节读取 —— FileStream 底层操作

// 适合复制文件、处理图片等场景
using (FileStream fs = new FileStream("source.jpg", FileMode.Open))
{
    // 读取文件大小
    long fileSize = fs.Length;
    Console.WriteLine($"文件大小: {fileSize} 字节 ({fileSize / 1024.0:F1} KB)");

    // 一次性读取全部字节
    byte[] buffer = new byte[fileSize];
    int bytesRead = fs.Read(buffer, 0, buffer.Length);
    Console.WriteLine($"实际读取: {bytesRead} 字节");

    // 可以查看前几个字节(文件头/魔数)
    Console.Write("前 8 字节: ");
    for (int i = 0; i < Math.Min(8, bytesRead); i++)
    {
        Console.Write($"{buffer[i]:X2} ");  // 16 进制显示
    }
    Console.WriteLine();
}

3.4 分块读取大文件

// 大文件不要一次性读完,分块处理
using (FileStream fs = new FileStream("largefile.dat", FileMode.Open))
{
    byte[] buffer = new byte[4096];  // 每次读 4KB
    int bytesRead;
    long totalRead = 0;

    while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
    {
        totalRead += bytesRead;
        // 处理这 bytesRead 个字节...
        Console.Write($"\r已读取: {totalRead} 字节");
    }
    Console.WriteLine($"\n读取完成,共 {totalRead} 字节");
}

3.5 完整示例——学生数据的二进制存储

using System;
using System.Collections.Generic;
using System.IO;

public class Student
{
    public string Name;
    public int Age;
    public int Score;
}

class Program
{
    // 保存学生列表为二进制文件
    static void SaveStudents(string path, List<Student> students)
    {
        using (BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create)))
        {
            writer.Write(students.Count);  // 先写数量
            foreach (var s in students)
            {
                writer.Write(s.Name);
                writer.Write(s.Age);
                writer.Write(s.Score);
            }
        }
        Console.WriteLine($"保存完成: {students.Count} 条记录");
    }

    // 从二进制文件读取学生列表
    static List<Student> LoadStudents(string path)
    {
        List<Student> students = new List<Student>();

        using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open)))
        {
            int count = reader.ReadInt32();  // 先读数量
            for (int i = 0; i < count; i++)
            {
                students.Add(new Student
                {
                    Name = reader.ReadString(),
                    Age = reader.ReadInt32(),
                    Score = reader.ReadInt32()
                });
            }
        }
        return students;
    }

    static void Main()
    {
        // 创建数据
        var students = new List<Student>
        {
            new Student { Name = "张三", Age = 18, Score = 92 },
            new Student { Name = "李四", Age = 19, Score = 85 },
            new Student { Name = "王五", Age = 18, Score = 76 },
        };

        // 保存
        SaveStudents("students.bin", students);

        // 读取
        var loaded = LoadStudents("students.bin");
        Console.WriteLine($"\n读取到 {loaded.Count} 条记录:");
        foreach (var s in loaded)
            Console.WriteLine($"  {s.Name} - {s.Age}岁 - {s.Score}分");
    }
}

四、读取 Excel 表格

4.1 需要安装的包

C# 本身不支持 Excel,需要用第三方库。推荐 ClosedXML(免费、开源、支持 .xlsx):

# 在 NuGet 包管理器控制台执行:
Install-Package ClosedXML

4.2 准备一个 Excel 文件

创建一个 students.xlsx,内容如下:

姓名 年龄 分数
张三 18 92
李四 19 85
王五 18 76
赵六 20 58
孙七 19 88

4.3 读取 Excel —— 基本操作

using System;
using ClosedXML.Excel;

class Program
{
    static void Main()
    {
        string path = "students.xlsx";

        using (var workbook = new XLWorkbook(path))  // 打开工作簿
        {
            var worksheet = workbook.Worksheet(1);    // 获取第一个工作表

            Console.WriteLine($"工作表名: {worksheet.Name}");
            Console.WriteLine($"数据范围: {worksheet.RangeUsed()?.RangeAddress}");
            Console.WriteLine();

            // 读取每个单元格
            var rows = worksheet.RangeUsed().RowsUsed();

            foreach (var row in rows)
            {
                // row.Cell(1) 是第 1 列,row.Cell(2) 是第 2 列...
                string name = row.Cell(1).GetString();
                string age = row.Cell(2).GetString();
                string score = row.Cell(3).GetString();

                Console.WriteLine($"姓名:{name,-6} 年龄:{age,-4} 分数:{score}");
            }
        }
    }
}

4.4 跳过标题行 + 解析数据类型

using System;
using System.Collections.Generic;
using ClosedXML.Excel;

public class Student
{
    public string Name;
    public int Age;
    public int Score;
}

class Program
{
    static void Main()
    {
        string path = "students.xlsx";
        List<Student> students = new List<Student>();

        using (var workbook = new XLWorkbook(path))
        {
            var worksheet = workbook.Worksheet(1);
            var rows = worksheet.RangeUsed().RowsUsed();

            bool isFirstRow = true;
            foreach (var row in rows)
            {
                if (isFirstRow)
                {
                    isFirstRow = false;
                    continue;  // 跳过标题行
                }

                students.Add(new Student
                {
                    Name = row.Cell(1).GetString(),
                    Age = row.Cell(2).GetValue<int>(),   // 直接获取数值类型
                    Score = row.Cell(3).GetValue<int>()
                });
            }
        }

        Console.WriteLine($"读取到 {students.Count} 名学生的数据:\n");
        foreach (var s in students)
            Console.WriteLine($"  {s.Name,-6} | {s.Age}岁 | {s.Score}分");

        Console.WriteLine($"\n  平均分: {students.Average(s => s.Score):F1}");
        Console.WriteLine($"  最高分: {students.Max(s => s.Score)}");
    }
}

4.5 读取指定行范围

// 读取 A2 到 C10 这个范围
var range = worksheet.Range("A2:C10");

// 或按行列索引读取
var cell = worksheet.Cell(3, 2);  // 第 3 行,第 2 列(B3)
Console.WriteLine($"B3 单元格的值: {cell.GetString()}");

// 遍历指定行范围
for (int row = 2; row <= 6; row++)  // 从第 2 行到第 6 行
{
    string name = worksheet.Cell(row, 1).GetString();
    if (string.IsNullOrEmpty(name)) break;  // 遇到空行就停

    int score = worksheet.Cell(row, 3).GetValue<int>();
    Console.WriteLine($"{name}: {score}分");
}

4.6 写入 Excel

using ClosedXML.Excel;

// 创建工作簿
using (var workbook = new XLWorkbook())
{
    var worksheet = workbook.Worksheets.Add("学生成绩");

    // 写标题
    worksheet.Cell(1, 1).Value = "姓名";
    worksheet.Cell(1, 2).Value = "年龄";
    worksheet.Cell(1, 3).Value = "分数";

    // 写数据
    worksheet.Cell(2, 1).Value = "张三";
    worksheet.Cell(2, 2).Value = 18;
    worksheet.Cell(2, 3).Value = 92;

    worksheet.Cell(3, 1).Value = "李四";
    worksheet.Cell(3, 2).Value = 19;
    worksheet.Cell(3, 3).Value = 85;

    // 保存
    workbook.SaveAs("output.xlsx");
    Console.WriteLine("Excel 文件已生成: output.xlsx");
}

五、读取 PDF 文件

5.1 需要安装的包

PDF 不是 C# 自带的,需要使用第三方库。推荐 UglyToad.PdfPig(免费、纯 C#):

Install-Package PdfPig

另一个选择是 iTextSharp(功能更强但商业用需付费),PdfPig 是 MIT 开源协议完全免费。

5.2 读取 PDF 中的文本

using System;
using UglyToad.PdfPig;

class Program
{
    static void Main()
    {
        string path = "document.pdf";

        using (var pdf = PdfDocument.Open(path))
        {
            Console.WriteLine($"PDF 信息:");
            Console.WriteLine($"  总页数: {pdf.NumberOfPages}");
            Console.WriteLine();

            // 遍历每一页
            foreach (var page in pdf.GetPages())
            {
                Console.WriteLine($"===== 第 {page.Number} 页 =====");

                // 获取这一页的全部文本
                string pageText = page.Text;
                Console.WriteLine(pageText);

                // 获取这一页的单词列表
                var words = page.GetWords();
                Console.WriteLine($"\n  本页共 {words.Count()} 个单词");
            }
        }
    }
}

5.3 逐字读取 + 获取位置信息

using UglyToad.PdfPig;

using (var pdf = PdfDocument.Open("document.pdf"))
{
    foreach (var page in pdf.GetPages())
    {
        Console.WriteLine($"===== 第 {page.Number} 页 =====");

        // 获取每个单词(带位置信息)
        foreach (var word in page.GetWords())
        {
            Console.WriteLine($"  \"{word.Text}\" "
                + $"位置: ({word.BoundingBox.Left:F0}, {word.BoundingBox.Top:F0}) "
                + $"字体: {word.FontName} 字号: {word.FontSize}");
        }
    }
}

5.4 更简单的方式——提取纯文本

using UglyToad.PdfPig;
using System.Text;

static string ExtractAllText(string pdfPath)
{
    StringBuilder sb = new StringBuilder();

    using (var pdf = PdfDocument.Open(pdfPath))
    {
        foreach (var page in pdf.GetPages())
        {
            sb.AppendLine(page.Text);
        }
    }

    return sb.ToString();
}

// 使用
string allText = ExtractAllText("document.pdf");
Console.WriteLine(allText);

六、文件操作的综合对比

6.1 各类型文件的读取方式

文件类型 推荐库/类 安装方式 难度
TXT/CSV File / StreamReader C# 自带 简单
二进制 FileStream / BinaryReader C# 自带 中等
Excel (.xlsx) ClosedXML NuGet 安装 中等
PDF PdfPig NuGet 安装 中等偏难
JSON System.Text.Json C# 自带 简单

6.2 读取方式的通用模式

// ✅ 通用读取模式:

// 1. 检查文件是否存在
if (!File.Exists(path))
{
    Console.WriteLine("文件不存在");
    return;
}

// 2. 使用 using 语句(自动关闭文件)
using (var resource = new SomeReader(path))
{
    // 3. 读取数据
    var data = resource.Read();

    // 4. 处理数据
    Process(data);

}  // ← 离开 using 时自动释放资源

6.3 异常处理——文件操作的必备

try
{
    string content = File.ReadAllText("data.txt");
    Console.WriteLine(content);
}
catch (FileNotFoundException)
{
    Console.WriteLine("错误:文件没找到,请检查文件路径");
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("错误:没有权限读取该文件");
}
catch (IOException ex)
{
    Console.WriteLine($"错误:读取文件时发生异常: {ex.Message}");
}

七、完整实战——多格式成绩汇总系统

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ClosedXML.Excel;

class Student
{
    public string Name;
    public int Score;
    public string Source;  // 数据来源

    public override string ToString() => $"{Name,-6} | {Score}分 | 来源:{Source}";
}

class Program
{
    static void Main()
    {
        Console.WriteLine("===== 多格式成绩汇总系统 =====\n");
        List<Student> allStudents = new List<Student>();

        // ===== 1. 读取 TXT 文件 =====
        string txtPath = "scores.txt";
        if (File.Exists(txtPath))
        {
            Console.WriteLine($"📝 读取 TXT: {txtPath}");
            var txtStudents = File.ReadAllLines(txtPath)
                .Where(line => !string.IsNullOrWhiteSpace(line))
                .Select(line => line.Split(','))
                .Where(parts => parts.Length >= 2)
                .Select(parts => new Student
                {
                    Name = parts[0].Trim(),
                    Score = int.Parse(parts[1].Trim()),
                    Source = "TXT"
                });
            allStudents.AddRange(txtStudents);
            Console.WriteLine($"   读取到 {txtStudents.Count()} 条\n");
        }
        else
        {
            Console.WriteLine($"⚠️ 文件不存在: {txtPath}\n");
        }

        // ===== 2. 读取 Excel 文件 =====
        string excelPath = "scores.xlsx";
        if (File.Exists(excelPath))
        {
            Console.WriteLine($"📊 读取 Excel: {excelPath}");
            try
            {
                using (var workbook = new XLWorkbook(excelPath))
                {
                    var worksheet = workbook.Worksheet(1);
                    var rows = worksheet.RangeUsed().RowsUsed().Skip(1); // 跳过标题

                    foreach (var row in rows)
                    {
                        string name = row.Cell(1).GetString().Trim();
                        if (string.IsNullOrEmpty(name)) break;

                        allStudents.Add(new Student
                        {
                            Name = name,
                            Score = row.Cell(2).GetValue<int>(),
                            Source = "Excel"
                        });
                    }
                }
                Console.WriteLine($"   读取完毕\n");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"   Excel 读取失败: {ex.Message}\n");
            }
        }
        else
        {
            Console.WriteLine($"⚠️ 文件不存在: {excelPath}\n");
        }

        // ===== 3. 汇总分析 =====
        if (allStudents.Count == 0)
        {
            Console.WriteLine("没有读取到任何数据!");
            return;
        }

        Console.WriteLine("===== 汇总结果 =====");
        Console.WriteLine($"总人数: {allStudents.Count}");

        foreach (var s in allStudents)
            Console.WriteLine($"  {s}");

        Console.WriteLine($"\n平均分: {allStudents.Average(s => s.Score):F1}");
        Console.WriteLine($"最高分: {allStudents.Max(s => s.Score)}");
        Console.WriteLine($"最低分: {allStudents.Min(s => s.Score)}");
        Console.WriteLine($"及格率: {(double)allStudents.Count(s => s.Score >= 60) / allStudents.Count * 100:F1}%");
    }
}

八、常见易错点(避坑指南)

坑1:忘记检查文件是否存在

// ❌ 直接读,文件不存在就崩溃
string text = File.ReadAllText("不存在的文件.txt");

// ✅ 先检查
if (File.Exists("文件.txt"))
{
    string text = File.ReadAllText("文件.txt");
}
else
{
    Console.WriteLine("文件不存在");
}

坑2:没有关闭文件流

// ❌ 忘记关闭
FileStream fs = new FileStream("data.txt", FileMode.Open);
// ... 操作用完没关闭,文件被锁住

// ✅ 用 using 自动关闭
using (FileStream fs = new FileStream("data.txt", FileMode.Open))
{
    // ... 操作
}  // 自动调用 fs.Dispose() 关闭文件

坑3:二进制文件读写顺序不一致

// 写入
writer.Write(42);
writer.Write("hello");
writer.Write(3.14);

// ❌ 读的时候顺序错了
// int x = reader.ReadInt32();
// double d = reader.ReadDouble();  // ← 出错!实际读到的是 "hello" 开头
// string s = reader.ReadString();

// ✅ 读的顺序必须和写完全一致
int x = reader.ReadInt32();
string s = reader.ReadString();
double d = reader.ReadDouble();

坑4:一次性读大文件导致内存溢出

// ❌ 大文件(如 500MB 的日志)一次性读入内存
string all = File.ReadAllText("huge_log.txt");  // 可能 OutOfMemoryException

// ✅ 用 StreamReader 逐行处理
using (StreamReader reader = new StreamReader("huge_log.txt"))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        ProcessLine(line);  // 逐行处理,只占一行内存
    }
}

坑5:Excel 读取时没有 disposed

// ❌ 没有释放 Excel 资源
var workbook = new XLWorkbook("data.xlsx");
var sheet = workbook.Worksheet(1);
// ... 用完后没释放

// ✅ 用 using 或手动 workbook.Dispose()
using (var workbook = new XLWorkbook("data.xlsx"))
{
    var sheet = workbook.Worksheet(1);
    // ...
}

坑6:路径中的反斜杠问题

// ❌ 单反斜杠在 C# 里是转义字符
// string path = "C:\data\file.txt";  // 编译错误!

// ✅ 三种正确写法
string path1 = "C:\\data\\file.txt";    // 双反斜杠
string path2 = @"C:\data\file.txt";     // @ 前缀(逐字字符串)
string path3 = "C:/data/file.txt";      // 正斜杠也行

坑7:编码问题——中文乱码

// ❌ 文件是 UTF-8 编码,但用默认编码读可能乱码
string text = File.ReadAllText("chinese.txt");  // 中文变乱码!

// ✅ 指定编码
string text = File.ReadAllText("chinese.txt", System.Text.Encoding.UTF8);

// StreamReader 也一样
using (var reader = new StreamReader("chinese.txt", Encoding.UTF8))
{
    string content = reader.ReadToEnd();
}

九、总结

文件读取速查表

文件类型 读方式 写方式
TXT 小文件 File.ReadAllText(path) File.WriteAllText(path, text)
TXT 大文件 new StreamReader(path) 逐行 new StreamWriter(path) 逐行
二进制固定格式 new BinaryReader(fs) new BinaryWriter(fs)
二进制底层 new FileStream(path, FileMode.Open) new FileStream(path, FileMode.Create)
Excel (.xlsx) new XLWorkbook(path) + Worksheet() new XLWorkbook() + SaveAs()
PDF PdfDocument.Open(path) + GetPages() (需其他库)

记忆口诀

文件操作三步走:检查存在、using 包裹、异常处理

文本小用 ReadAll,文本大用 StreamReader
二进制用 Binary,顺序读写要对齐
Excel 要装 ClosedXML,工作簿里找工作表
PDF 提取纯文本,PdfPig 免费又方便

读完记得关,using 帮你管
路径反斜杠,要么写俩要么加 @

一句话总结:C# 的文件操作都围绕 System.IO 展开——TXT 小文件用 File.ReadAllText,大文件用 StreamReader 逐行读;二进制用 FileStream + BinaryReader(读写顺序必须一致);Excel 需要第三方库(推荐 ClosedXML);PDF 需要第三方库(推荐 PdfPig)。所有文件操作都用 using 包起来,读之前检查 File.Exists

0
博主关闭了当前页面的评论