当前位置: 首页 > news >正文

C#读取文件, IO 类属性及使用示例

C#读取文件, IO 类属性及使用示例

以下是包含属性说明、带注释的使用示例的汇总表格,清晰展示各属性的功能及实际应用场景:

  • 类名属性(非静态)带注释的使用示例
    BinaryReaderBaseStream// 创建文件流,用于读取二进制文件 using (var fs = new FileStream("data.bin", FileMode.Open)) { // 基于文件流创建二进制阅读器 using (var reader = new BinaryReader(fs)) { // 获取当前阅读器的基础流(此处为FileStream) FileStream baseStream = (FileStream)reader.BaseStream; // 输出基础流关联的文件名 Console.WriteLine($"基础流文件:{baseStream.Name}"); } }
    BinaryWriterBaseStreamusing (var fs = new FileStream("data.bin", FileMode.Create)) // 创建文件流,用于写入二进制文件 using (var writer = new BinaryWriter(fs)) // 基于文件流创建二进制写入器 { // 获取当前写入器的基础流(此处为FileStream) FileStream baseStream = (FileStream)writer.BaseStream; Console.WriteLine($"基础流当前位置:{baseStream.Position}"); // 输出写入前的流位置(初始为0) writer.Write(123); // 写入数据后,位置会更新 Console.WriteLine($"写入后基础流位置:{baseStream.Position}"); }
    BufferedStreamLengthusing (var fs = new FileStream("file.txt", FileMode.Open)) // 打开现有文件 using (var buffered = new BufferedStream(fs)) // 用缓冲流包装文件流(提升读写性能) { // 获取流的总长度(字节数,即文件大小) long totalBytes = buffered.Length; Console.WriteLine($"文件总大小:{totalBytes} 字节"); }
    Positionusing (var fs = new FileStream("file.txt", FileMode.Open)) using (var buffered = new BufferedStream(fs)) { // 设置流的当前操作位置(从0开始,此处移动到第10个字节) buffered.Position = 10; Console.WriteLine($"当前操作位置:{buffered.Position}"); // 输出:10 // 从当前位置读取数据 byte[] buffer = new byte[5]; buffered.Read(buffer, 0, 5); // 读取从位置10开始的5个字节 }
    CanReadusing (var fs = new FileStream("file.txt", FileMode.Open)) using (var buffered = new BufferedStream(fs)) { // 判断流是否支持读取操作(取决于基础流的打开方式) if (buffered.CanRead) { Console.WriteLine("流可读取"); byte[] data = new byte[100]; buffered.Read(data, 0, 100); // 执行读取 } else { Console.WriteLine("流不可读取"); } }
    CanWriteusing (var fs = new FileStream("file.txt", FileMode.OpenOrCreate)) // 以可读写模式打开文件 using (var buffered = new BufferedStream(fs)) { // 判断流是否支持写入操作 if (buffered.CanWrite) { Console.WriteLine("流可写入"); byte[] data = Encoding.UTF8.GetBytes("测试写入"); buffered.Write(data, 0, data.Length); // 执行写入 } else { Console.WriteLine("流不可写入"); } }
    BufferSizeusing (var fs = new FileStream("largeFile.dat", FileMode.Open)) // 创建缓冲流时指定缓冲区大小为8KB(默认4KB,大文件可适当调大) using (var buffered = new BufferedStream(fs, 8192)) { // 获取当前缓冲区大小(字节) int bufferSize = buffered.BufferSize; Console.WriteLine($"缓冲区大小:{bufferSize} 字节"); // 输出:8192 // 缓冲区越大,减少IO次数越多,适合大文件读写 }
    DirectoryInfoName// 创建目录信息实例(指向C盘的test目录) var dir = new DirectoryInfo(@"C:\test"); // 获取目录的名称(不含路径) string dirName = dir.Name; Console.WriteLine($"目录名:{dirName}"); // 输出:test
    FullNamevar dir = new DirectoryInfo(@"C:\test"); // 获取目录的完整路径(包含盘符和所有父目录) string fullPath = dir.FullName; Console.WriteLine($"完整路径:{fullPath}"); // 输出:C:\test
    Parent// 指向子目录C:\test\subdir var dir = new DirectoryInfo(@"C:\test\subdir"); // 获取父目录信息(此处为C:\test) DirectoryInfo parentDir = dir.Parent; if (parentDir != null) // 根目录(如C:\)的Parent为null,需判断 { Console.WriteLine($"父目录路径:{parentDir.FullName}"); // 输出:C:\test }
    Existsvar dir = new DirectoryInfo(@"C:\newDir"); // 判断目录是否存在 if (!dir.Exists) { dir.Create(); // 不存在则创建目录 Console.WriteLine("目录已创建"); } else { Console.WriteLine("目录已存在"); }
    CreationTimevar dir = new DirectoryInfo(@"C:\test"); // 获取目录的创建时间(本地时间) DateTime createTime = dir.CreationTime; Console.WriteLine($"创建时间:{createTime:yyyy-MM-dd HH:mm:ss}"); // 输出格式:2024-01-01 10:30:00
    LastWriteTimevar dir = new DirectoryInfo(@"C:\test"); // 获取目录最后一次修改的时间(如新增/删除子文件/目录时更新) DateTime lastWrite = dir.LastWriteTime; Console.WriteLine($"最后修改时间:{lastWrite:yyyy-MM-dd HH:mm:ss}");
    DriveInfoName// 创建驱动器信息实例(指向C盘) var drive = new DriveInfo("C:"); // 获取驱动器名称(格式为"盘符:\") string driveName = drive.Name; Console.WriteLine($"驱动器名:{driveName}"); // 输出:C:\
    DriveTypevar drive = new DriveInfo("C:"); // 获取驱动器类型(Fixed为固定磁盘,Removable为可移动磁盘等) DriveType type = drive.DriveType; Console.WriteLine($"驱动器类型:{type}"); // 输出:Fixed(机械/固态硬盘)
    TotalSizevar drive = new DriveInfo("C:"); // 先判断驱动器是否就绪(如U盘插入且可访问) if (drive.IsReady) { // 获取驱动器总容量(字节) long totalSize = drive.TotalSize; // 转换为GB(1GB=1024^3字节) Console.WriteLine($"总容量:{totalSize / 1024 / 1024 / 1024} GB"); }
    AvailableFreeSpacevar drive = new DriveInfo("C:"); if (drive.IsReady) { // 获取驱动器可用空间(字节,用户可使用的剩余空间) long freeSpace = drive.AvailableFreeSpace; Console.WriteLine($"可用空间:{freeSpace / 1024 / 1024 / 1024} GB"); }
    DriveFormatvar drive = new DriveInfo("C:"); if (drive.IsReady) { // 获取驱动器的文件系统格式(如NTFS、FAT32) string format = drive.DriveFormat; Console.WriteLine($"文件系统:{format}"); // 输出:NTFS }
    IsReadyvar drive = new DriveInfo("D:"); // 判断驱动器是否就绪(如光盘放入、U盘插入且挂载成功) if (drive.IsReady) { Console.WriteLine("驱动器已就绪,可访问"); } else { Console.WriteLine("驱动器未就绪(如未插入或未挂载)"); }
    FileInfoName// 创建文件信息实例(指向当前目录的test.txt) var file = new FileInfo("test.txt"); // 获取文件名(含扩展名,不含路径) string fileName = file.Name; Console.WriteLine($"文件名:{fileName}"); // 输出:test.txt
    FullNamevar file = new FileInfo("test.txt"); // 获取文件的完整路径(包含盘符、目录和文件名) string fullPath = file.FullName; Console.WriteLine($"完整路径:{fullPath}"); // 输出:C:\当前目录\test.txt
    Lengthvar file = new FileInfo("test.txt"); // 判断文件是否存在(不存在时Length会报错) if (file.Exists) { // 获取文件大小(字节数) long fileSize = file.Length; Console.WriteLine($"文件大小:{fileSize} 字节"); }
    Existsvar file = new FileInfo("temp.txt"); // 判断文件是否存在 if (file.Exists) { file.Delete(); // 存在则删除 Console.WriteLine("文件已删除"); } else { file.Create().Dispose(); // 不存在则创建 Console.WriteLine("文件已创建"); }
    CreationTimevar file = new FileInfo("test.txt"); // 获取文件的创建时间 DateTime createTime = file.CreationTime; Console.WriteLine($"创建时间:{createTime:yyyy-MM-dd HH:mm:ss}");
    LastWriteTimevar file = new FileInfo("test.txt"); // 获取文件最后一次修改的时间(写入内容后更新) DateTime lastWrite = file.LastWriteTime; Console.WriteLine($"最后修改时间:{lastWrite:yyyy-MM-dd HH:mm:ss}");
    IsReadOnlyvar file = new FileInfo("test.txt"); // 判断文件是否为只读 if (file.IsReadOnly) { Console.WriteLine("文件是只读的,修改前需取消只读"); file.IsReadOnly = false; // 取消只读属性 } // 现在可以写入文件 using (var sw = file.AppendText()) { sw.WriteLine("新增内容"); }
    FileStreamLengthusing (var fs = new FileStream("data.dat", FileMode.Open)) // 打开文件流 { // 获取文件总长度(字节,即文件大小) long fileLength = fs.Length; Console.WriteLine($"文件总长度:{fileLength} 字节"); }
    Positionusing (var fs = new FileStream("data.dat", FileMode.Open)) { // 设置当前读写位置(从0开始,此处移动到第5个字节) fs.Position = 5; Console.WriteLine($"当前位置:{fs.Position}"); // 输出:5 // 从当前位置读取3个字节 byte[] buffer = new byte[3]; fs.Read(buffer, 0, 3); // 读取位置5-7的字节 }
    CanRead// 以只读模式打开文件流(FileAccess.Read) using (var fs = new FileStream("data.dat", FileMode.Open, FileAccess.Read)) { // 判断是否有读取权限(此处为true) if (fs.CanRead) { Console.WriteLine("文件流可读取"); byte[] data = new byte[100]; fs.Read(data, 0, 100); } }
    CanWrite// 以只写模式打开文件流(FileAccess.Write) using (var fs = new FileStream("data.dat", FileMode.Open, FileAccess.Write)) { // 判断是否有写入权限(此处为true) if (fs.CanWrite) { Console.WriteLine("文件流可写入"); byte[] data = Encoding.UTF8.GetBytes("写入内容"); fs.Write(data, 0, data.Length); } }
    Nameusing (var fs = new FileStream("log.txt", FileMode.Open)) { // 获取文件流关联的文件名(含路径) string fileName = fs.Name; Console.WriteLine($"关联文件:{fileName}"); // 输出:C:\当前目录\log.txt }
    IsAsync// 创建异步模式的文件流(useAsync: true) using (var fs = new FileStream("async.dat", FileMode.Create, FileAccess.Write, FileShare.None, 4096, useAsync: true)) { // 判断是否为异步模式(此处为true) bool isAsync = fs.IsAsync; Console.WriteLine($"是否异步模式:{isAsync}"); // 输出:True // 适合配合async/await进行异步IO操作 }
    MemoryStreamLengthusing (var ms = new MemoryStream()) // 创建内存流(数据存储在内存中) { // 向内存流写入数据 byte[] data = Encoding.UTF8.GetBytes("内存数据测试"); ms.Write(data, 0, data.Length); // 获取内存流中数据的总长度(字节) long streamLength = ms.Length; Console.WriteLine($"内存流长度:{streamLength} 字节"); // 输出:14("内存数据测试"的UTF8字节数) }
    Positionusing (var ms = new MemoryStream()) { byte[] data = Encoding.UTF8.GetBytes("abcdef"); ms.Write(data, 0, data.Length); // 写入6个字节(a(0),b(1),c(2),d(3),e(4),f(5)) // 移动到位置2(对应字符'c') ms.Position = 2; Console.WriteLine($"当前位置:{ms.Position}"); // 输出:2 // 从位置2读取2个字节(c和d) byte[] buffer = new byte[2]; ms.Read(buffer, 0, 2); Console.WriteLine(Encoding.UTF8.GetString(buffer)); // 输出:cd }
    Capacity// 创建初始容量为100字节的内存流 using (var ms = new MemoryStream(100)) { // 获取当前容量(可分配的内存大小) int capacity = ms.Capacity; Console.WriteLine($"初始容量:{capacity} 字节"); // 输出:100 // 当写入数据超过容量时,内存流会自动扩容,但手动调整可减少扩容次数 ms.Capacity = 200; // 手动调整容量为200字节 Console.WriteLine($"调整后容量:{ms.Capacity} 字节"); // 输出:200 }
    ToArray()(方法)using (var ms = new MemoryStream()) { // 向内存流写入数据 ms.Write(Encoding.UTF8.GetBytes("hello memory"), 0, 12); // 将内存流中的数据转换为字节数组(常用于保存或传输) byte[] result = ms.ToArray(); Console.WriteLine($"转换后数组长度:{result.Length}"); // 输出:12 Console.WriteLine(Encoding.UTF8.GetString(result)); // 输出:hello memory }
    StreamReaderBaseStreamusing (var fs = new FileStream("text.txt", FileMode.Open)) using (var reader = new StreamReader(fs)) // 基于文件流创建文本阅读器 { // 获取基础流(此处为FileStream) FileStream baseStream = (FileStream)reader.BaseStream; Console.WriteLine($"基础流文件:{baseStream.Name}"); // 输出:text.txt // 可通过基础流获取文件大小等信息 Console.WriteLine($"文件大小:{baseStream.Length} 字节"); }
    CurrentEncoding// 用UTF8编码创建文本阅读器(默认编码可能随系统变化,建议显式指定) using (var reader = new StreamReader("text.txt", Encoding.UTF8)) { // 获取当前使用的编码 Encoding encoding = reader.CurrentEncoding; Console.WriteLine($"使用编码:{encoding.BodyName}"); // 输出:utf-8(编码的标准名称) }
    EndOfStreamusing (var reader = new StreamReader("log.txt")) { // 循环读取,直到流末尾(EndOfStream为true) while (!reader.EndOfStream) { string line = reader.ReadLine(); // 逐行读取 Console.WriteLine(line); } }
    StreamWriterBaseStreamusing (var fs = new FileStream("output.txt", FileMode.Create)) using (var writer = new StreamWriter(fs)) // 基于文件流创建文本写入器 { // 获取基础流(此处为FileStream) FileStream baseStream = (FileStream)writer.BaseStream; Console.WriteLine($"基础流位置:{baseStream.Position}"); // 初始为0 writer.WriteLine("测试文本"); // 写入后,基础流位置更新 Console.WriteLine($"写入后位置:{baseStream.Position}"); }
    Encoding// 用Unicode编码创建文本写入器(每个字符占2字节) using (var writer = new StreamWriter("unicode.txt", false, Encoding.Unicode)) { // 获取写入时使用的编码 Encoding encoding = writer.Encoding; Console.WriteLine($"写入编码:{encoding.BodyName}"); // 输出:utf-16(Unicode的标准名称) writer.WriteLine("中文测试"); // 用Unicode编码写入 }
    AutoFlushusing (var writer = new StreamWriter("log.txt")) { // 设置AutoFlush为true:每次写入后自动刷新缓冲区(默认false,需手动调用Flush()或关闭流才写入) writer.AutoFlush = true; writer.WriteLine("操作1完成"); // 写入后立即刷新到文件(无需等待) writer.WriteLine("操作2完成"); // 立即刷新,确保断电等情况不丢失数据 }

表格中每个示例均通过注释解释了属性的作用、代码逻辑及注意事项(如空值判断、权限检查等),便于理解属性的实际用法和场景限制。

1. 类与属性对应表

类名主要属性(非静态)属性描述
BinaryReaderBaseStream获取当前阅读器的基础流(如 FileStream)
BinaryWriterBaseStream获取当前写入器的基础流(如 FileStream)
BufferedStreamLengthPositionCanReadCanWriteBufferSize流长度、当前位置、是否可读写、缓冲区大小
DirectoryInfoNameFullNameParentExistsCreationTimeLastWriteTime目录名、完整路径、父目录、是否存在、创建时间、最后写入时间
DriveInfoNameDriveTypeTotalSizeAvailableFreeSpaceDriveFormatIsReady驱动器名(如 "C:")、驱动器类型、总容量、可用空间、文件系统、是否就绪
FileInfoNameFullNameLengthExistsCreationTimeLastWriteTimeIsReadOnly文件名、完整路径、文件大小(字节)、是否存在、创建时间、最后写入时间、是否只读
FileStreamLengthPositionCanReadCanWriteNameIsAsync流长度、当前位置、是否可读写、关联文件名、是否异步操作
MemoryStreamLengthPositionCapacityToArray()(方法,常作为属性使用)流长度、当前位置、容量(可分配的内存大小)、转换为字节数组
StreamReaderBaseStreamCurrentEncodingEndOfStream基础流、当前编码(如 UTF8)、是否到达流末尾
StreamWriterBaseStreamEncodingAutoFlush基础流、写入编码、是否自动刷新缓冲区

2. 属性使用示例表(C# 语法)

类名属性名使用示例代码代码说明
BinaryReaderBaseStreamvar reader = new BinaryReader(File.Open("data.bin", FileMode.Open));创建 BinaryReader 实例,关联文件流
Stream baseStream = reader.BaseStream;获取阅读器的基础流(如 FileStream)
BinaryWriterBaseStreamvar writer = new BinaryWriter(File.Open("data.bin", FileMode.Create));创建 BinaryWriter 实例,关联文件流
Stream baseStream = writer.BaseStream;获取写入器的基础流(如 FileStream)
BufferedStreamLengthvar bufferStream = new BufferedStream(File.Open("file.txt", FileMode.Open));创建缓冲流实例
long length = bufferStream.Length;获取缓冲流的总长度(字节数)
Positionlong pos = bufferStream.Position;获取当前在流中的位置(字节偏移量)
CanReadbool canRead = bufferStream.CanRead;判断缓冲流是否支持读取操作
CanWritebool canWrite = bufferStream.CanWrite;判断缓冲流是否支持写入操作
BufferSizeint bufferSize = bufferStream.BufferSize;获取缓冲区的大小(字节数)
DirectoryInfoNamevar dir = new DirectoryInfo(@"C:\test");创建目录信息实例
string name = dir.Name;获取目录名(如 "test",不含路径)
FullNamestring fullPath = dir.FullName;获取目录的完整路径(如 "C:\test")
ParentDirectoryInfo parent = dir.Parent;获取父目录的 DirectoryInfo 实例
Existsbool exists = dir.Exists;判断目录是否实际存在
CreationTimeDateTime createTime = dir.CreationTime;获取目录的创建时间(本地时间)
LastWriteTimeDateTime lastWrite = dir.LastWriteTime;获取目录最后被修改的时间(本地时间)
DriveInfoNamevar drive = new DriveInfo("C:");创建驱动器信息实例
string driveName = drive.Name;获取驱动器名(如 "C:")
DriveTypeDriveType type = drive.DriveType;获取驱动器类型(如 Fixed (固定磁盘)、Removable (可移动设备))
TotalSizelong totalSize = drive.TotalSize;获取驱动器总容量(字节,需驱动器就绪)
AvailableFreeSpacelong freeSpace = drive.AvailableFreeSpace;获取驱动器可用空间(字节,需驱动器就绪)
DriveFormatstring format = drive.DriveFormat;获取文件系统格式(如 NTFS、FAT32,需驱动器就绪)
IsReadybool isReady = drive.IsReady;判断驱动器是否就绪(可访问,如 U 盘是否插入)
FileInfoNamevar file = new FileInfo("document.txt");创建文件信息实例
string fileName = file.Name;获取文件名(如 "document.txt",不含路径)
FullNamestring fullPath = file.FullName;获取文件的完整路径
Lengthlong fileSize = file.Length;获取文件大小(字节数,文件需存在)
Existsbool exists = file.Exists;判断文件是否实际存在
CreationTimeDateTime createTime = file.CreationTime;获取文件的创建时间(本地时间)
LastWriteTimeDateTime lastWrite = file.LastWriteTime;获取文件最后被修改的时间(本地时间)
IsReadOnlybool isReadOnly = file.IsReadOnly;判断文件是否设置了只读属性
FileStreamLengthusing (var fs = new FileStream("data.dat", FileMode.Open))创建文件流实例(using 确保自动释放资源)
long length = fs.Length;获取文件流的总长度(字节数)
Positionlong pos = fs.Position;获取当前在文件流中的位置(字节偏移量)
CanReadbool canRead = fs.CanRead;判断文件流是否支持读取操作
CanWritebool canWrite = fs.CanWrite;判断文件流是否支持写入操作
Namestring name = fs.Name;获取文件流关联的文件名(含路径)
IsAsyncbool isAsync = fs.IsAsync;判断文件流是否为异步操作模式(构造时指定)
MemoryStreamLengthvar ms = new MemoryStream();创建内存流实例
long length = ms.Length;获取内存流中已写入数据的长度(字节)
Positionlong pos = ms.Position;获取当前在内存流中的位置(字节偏移量)
Capacityint capacity = ms.Capacity;获取内存流的容量(可容纳的最大字节数,可动态扩展)
ToArray()byte[] data = ms.ToArray();将内存流中的数据转换为字节数组(常用作属性使用)
StreamReaderBaseStreamusing (var sr = new StreamReader("text.txt"))创建流读取器实例(默认 UTF8 编码)
Stream baseStream = sr.BaseStream;获取读取器的基础流(如 FileStream)
CurrentEncodingEncoding encoding = sr.CurrentEncoding;获取当前使用的文本编码(如 UTF8)
EndOfStreambool isEnd = sr.EndOfStream;判断是否已到达流的末尾(是否还有可读取内容)
StreamWriterBaseStreamusing (var sw = new StreamWriter("output.txt"))创建流写入器实例(默认 UTF8 编码)
Stream baseStream = sw.BaseStream;获取写入器的基础流(如 FileStream)
EncodingEncoding encoding = sw.Encoding;获取写入时使用的文本编码
AutoFlushbool autoFlush = sw.AutoFlush;判断是否启用自动刷新(每次写入后自动刷新缓冲区到基础流)

注释说明

  • 示例代码均基于.NET Framework/.NET Core 的System.IO命名空间,使用前需导入该命名空间(using System.IO;)。

  • 涉及文件操作的类(如FileStreamStreamReader)建议使用using语句块,确保资源自动释放。

  • 部分属性(如DriveInfo.TotalSize)需要驱动器处于就绪状态(IsReady == true)才能正常获取值,否则可能抛出异常。

补充:

// 获取文件信息FileInfo fileInfo = new FileInfo(filePath);// 检查是否为隐藏文件bool isHidden = (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden;// 获取目录信息DirectoryInfo dirInfo = new DirectoryInfo(directoryPath);// 检查是否为隐藏目录bool isHidden = (dirInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden;

C# 中Encoding

以下是 C# 中Encoding类的核心知识点分析表格,涵盖基本概念、常用成员、派生类及注意事项:

类别具体内容说明 / 示例
基本概念命名空间System.Text(需导入该命名空间才能使用)
核心作用处理字符编码与字节流的转换,解决内存中 Unicode 字符(UTF-16)与存储 / 传输字节的映射问题
编码本质将字符(char)转换为字节(byte)序列(编码),或反之(解码)
常用静态属性(预定义编码)Encoding.ASCII7 位 ASCII 编码,仅支持字符 0-127(超出范围会替换为?
Encoding.UTF8UTF-8 编码(可变长度,1-4 字节表示一个字符),兼容 ASCII,支持全球字符
Encoding.UnicodeUTF-16 编码(小端序,2 字节表示大部分字符,特殊字符用 4 字节)
Encoding.BigEndianUnicodeUTF-16 编码(大端序,字节顺序与Unicode相反)
Encoding.UTF32UTF-32 编码(固定 4 字节表示一个字符,空间开销大但转换简单)
Encoding.Default系统默认编码(与操作系统区域设置相关,如中文系统可能为 GB2312/GBK,不推荐跨平台使用)
常用方法GetBytes(string s)将字符串编码为字节数组(核心编码方法) 示例:byte[] bytes = Encoding.UTF8.GetBytes("Hello");
GetString(byte[] bytes)将字节数组解码为字符串(核心解码方法) 示例:string s = Encoding.UTF8.GetString(bytes);
GetEncoder()获取用于连续编码的Encoder对象(处理大文本时分批编码更高效)
GetDecoder()获取用于连续解码的Decoder对象(处理大字节流时分批解码更高效)
GetByteCount(string s)计算将字符串编码为字节数组所需的字节数
GetCharCount(byte[] bytes)计算将字节数组解码为字符所需的字符数
主要派生类ASCIIEncodingEncoding.ASCII的具体实现,仅支持 ASCII 字符
UTF8EncodingEncoding.UTF8的具体实现,可通过构造函数指定是否包含 BOM(字节顺序标记) 示例:new UTF8Encoding(encoderShouldEmitUTF8Identifier: true)(带 BOM)
UnicodeEncodingEncoding.Unicode的具体实现(小端序 UTF-16)
UTF32EncodingEncoding.UTF32的具体实现
注意事项编码与解码一致性编码和解码必须使用相同的编码格式,否则会出现乱码
BOM(字节顺序标记)UTF-8/UTF-16 等可能包含 BOM(如 UTF-8 的 BOM 为0xEF,0xBB,0xBF),用于标识编码类型,需根据场景决定是否保留
Default编码的风险依赖系统环境,跨平台(如 Windows 与 Linux)使用可能导致编码不一致,建议显式指定编码(如 UTF8)
异常处理解码无效字节时默认替换为,可通过DecoderFallback自定义错误处理逻辑

总结

Encoding类是 C# 中处理字符与字节转换的核心类,通过预定义的静态属性(如UTF8)可快速使用常见编码,核心方法GetBytesGetString实现基本的编码 / 解码操作。实际开发中应优先使用 UTF-8 等跨平台编码,避免依赖Default编码,并注意编码和解码的一致性以防止乱码。

以下是 C# 中Encoding类的知识点分析及代码示例表格,包含核心用法、常见场景及注意事项:

知识点分类具体内容 / API代码示例示例说明
基础信息命名空间using System.Text;必须导入该命名空间才能使用Encoding类及其派生类
核心功能-实现字符与字节的相互转换(编码:char→byte;解码:byte→char)
常用静态编码Encoding.ASCIIbyte[] asciiBytes = Encoding.ASCII.GetBytes("A±");ASCII 仅支持 0-127 字符,超出范围(如 "±")会被替换为?,结果为[65, 63]
Encoding.UTF8byte[] utf8Bytes = Encoding.UTF8.GetBytes("你好");UTF-8 编码中 "你好" 占 6 字节(每个汉字 3 字节),结果为[228,189,160,229,165,189]
Encoding.Unicodebyte[] unicodeBytes = Encoding.Unicode.GetBytes("A");UTF-16(小端序)中 "A" 占 2 字节,结果为[65, 0]
Encoding.BigEndianUnicodebyte[] beBytes = Encoding.BigEndianUnicode.GetBytes("A");UTF-16(大端序)中 "A" 占 2 字节,结果为[0, 65]
Encoding.UTF32byte[] utf32Bytes = Encoding.UTF32.GetBytes("A");UTF-32 中 "A" 占 4 字节,结果为[65, 0, 0, 0](小端序)
核心方法GetBytes(string)string str = "Test"; byte[] bytes = Encoding.UTF8.GetBytes(str);将字符串编码为字节数组,bytes结果为[84, 101, 115, 116]
GetString(byte[])byte[] bytes = {84, 101, 115, 116}; string str = Encoding.UTF8.GetString(bytes);将字节数组解码为字符串,str结果为 "Test"
GetByteCount(string)int count = Encoding.UTF8.GetByteCount("Hello");计算编码所需字节数,结果为 5("Hello" 的 UTF-8 编码占 5 字节)
GetCharCount(byte[])byte[] bytes = {72, 101, 108, 108, 111}; int count = Encoding.UTF8.GetCharCount(bytes);计算解码所得字符数,结果为 5
派生类特性UTF8Encoding(带 BOM 控制)var utf8WithBom = new UTF8Encoding(true); byte[] bomBytes = utf8WithBom.GetPreamble();构造带 BOM 的 UTF-8 编码,bomBytes结果为[0xEF, 0xBB, 0xBF](BOM 标识)
ASCIIEncoding(错误处理)var ascii = new ASCIIEncoding(); byte[] errBytes = ascii.GetBytes("é");ASCII 不支持 "é",默认替换为?errBytes结果为[63]
常见问题处理编码不一致导致乱码byte[] utf8Bytes = Encoding.UTF8.GetBytes("中文"); string乱码 = Encoding.ASCII.GetString(utf8Bytes);用 ASCII 解码 UTF-8 字节数组,结果为乱码(如 "??")
处理无效字节(替换字符)byte[] invalidBytes = {0xFF, 0xFF}; string result = Encoding.UTF8.GetString(invalidBytes);无效 UTF-8 字节会被替换为result结果为 "�"
系统默认编码的风险Encoding defaultEnc = Encoding.Default;Default依赖系统设置(如中文 Windows 可能为 GBK),跨平台可能不一致,不推荐使用
高级用法批量编码(Encoder)Encoder encoder = Encoding.UTF8.GetEncoder(); char[] chars = "Test".ToCharArray(); byte[] buffer = new byte[10]; encoder.GetBytes(chars, 0, chars.Length, buffer, 0, true);用于大文本分批编码,提升性能
批量解码(Decoder)Decoder decoder = Encoding.UTF8.GetDecoder(); byte[] bytes = {84, 101, 115, 116}; char[] chars = new char[10]; decoder.GetChars(bytes, 0, bytes.Length, chars, 0);用于大字节流分批解码,提升性能

关键说明:

  1. 编码一致性:编码(GetBytes)和解码(GetString)必须使用同一种编码格式,否则必然出现乱码。

  2. BOM 作用:字节顺序标记(BOM)用于标识编码类型(如 UTF-8 的 BOM),但在跨系统传输时可能需要移除(如 HTTP 协议通常不需要 BOM)。

  3. 异常处理:可通过EncoderFallbackDecoderFallback自定义无效字符 / 字节的处理逻辑(如抛出异常而非默认替换)。

  4. 推荐编码:优先使用UTF8,因其兼容 ASCII、支持全球字符且跨平台性好。

通过上述示例,可清晰理解Encoding类在字符与字节转换中的核心用法及潜在问题。

C# 常用对话框

以下是整理后的 C# 常用对话框汇总表格、各对话框属性详情表及完整实例代码,便于系统学习和查阅:

一、常用对话框汇总表

对话框类型核心用途核心返回属性(获取用户选择)典型场景关键命名空间
OpenFileDialog选择已存在的文件(支持多文件)FileName(文件路径)打开文档、导入数据System.Windows.Forms
SaveFileDialog指定文件保存路径FileName(保存路径)文档另存为、导出文件System.Windows.Forms
FolderBrowserDialog选择文件夹(支持新建)SelectedPath(文件夹路径)设置存储目录、批量处理System.Windows.Forms
ColorDialog选择颜色(支持自定义)Color(选中颜色)设置文本 / 背景色System.Windows.Forms
FontDialog选择字体(类型 / 大小 / 样式)Font(选中字体)文本格式设置System.Windows.Forms
PrintDialog配置打印参数(打印机 / 范围 / 份数)PrinterSettings(打印设置)文档打印前配置System.Drawing.Printing

二、各对话框属性详情表

1. OpenFileDialog(文件选择对话框)
属性名称作用描述数据类型示例值
核心属性
FileName获取用户选中的单个文件完整路径string"F:\\文档\\笔记.txt"
InitialDirectory设置打开时的初始目录string"C:\\Users\\Documents"
Filter筛选文件类型(格式:" *. 扩展名")显示名string" 文本文件*.txt图片文件.png;.jpg"
Title设置对话框标题string"请选择要打开的文件"
RestoreDirectory关闭后是否还原原目录booltrue
扩展属性
Multiselect是否允许选择多个文件booltrue(多选时用FileNames数组)
2. SaveFileDialog(文件保存对话框)
属性名称作用描述数据类型示例值
核心属性(与 OpenFileDialog 基本一致)
FileName获取用户输入的保存文件路径string"C:\\导出\\数据.csv"
Filter限制保存文件类型string"Excel 文件| *.xlsx | 所有文件 | *.*"
OverwritePrompt若文件已存在,是否提示覆盖booltrue(默认值)
3. FolderBrowserDialog(文件夹选择对话框)
属性名称作用描述数据类型示例值
核心属性
SelectedPath获取选中的文件夹路径string"D:\\项目\\素材"
Description对话框内的描述文本(标题下方)string"请选择存放备份的文件夹"
特有属性
ShowNewFolderButton是否显示 "新建文件夹" 按钮booltrue
RootFolder初始浏览的根目录(系统特殊文件夹)Environment.SpecialFolderEnvironment.SpecialFolder.Desktop(桌面)
4. ColorDialog(颜色对话框)
属性名称作用描述数据类型示例值
核心属性
Color获取用户选中的颜色System.Drawing.ColorColor.RedColor.FromArgb(255,0,0)
特有属性
AllowFullOpen是否允许打开自定义颜色面板boolfalse(禁用自定义)
FullOpen打开时是否直接显示自定义颜色面板booltrue
SolidColorOnly是否只允许选择纯色(禁用渐变色)booltrue
5. FontDialog(字体对话框)
属性名称作用描述数据类型示例值
核心属性
Font获取选中的字体(含名称 / 大小 / 样式)System.Drawing.Fontnew Font("微软雅黑",12,FontStyle.Bold)
扩展属性
ShowColor是否允许选择字体颜色booltrue
MinSize/MaxSize限制可选字体的最小 / 最大尺寸float8(最小 8 号字)
6. PrintDialog(打印对话框)
属性名称作用描述数据类型示例值
核心属性
PrinterSettings获取打印设置(打印机 / 份数 / 范围等)PrinterSettingsPrinterSettings.PrinterName(打印机名称)
Document关联需要打印的文档对象PrintDocumentnew PrintDocument()
特有属性
AllowPrintToFile是否允许 "打印到文件"booltrue
AllowSelection是否允许打印选中内容booltrue
Copies设置打印份数short2(打印 2 份)

三、完整实例代码(含所有对话框)

以下是一个包含 6 种对话框的完整 WinForm 示例,通过按钮触发不同对话框:

using System;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Windows.Forms;namespace DialogDemo
{public partial class MainForm : Form{public MainForm(){InitializeComponent();// 初始化按钮(实际开发中可在设计器拖放)InitButtons();}// 初始化触发对话框的按钮private void InitButtons(){this.Width = 600;this.Height = 400;this.Text = "C#常用对话框示例";// 按钮布局(垂直排列)int yPos = 30;string[] btnTexts = {"打开文件对话框", "保存文件对话框", "文件夹选择对话框","颜色对话框", "字体对话框", "打印对话框"};EventHandler[] btnEvents = {btnOpenFile_Click, btnSaveFile_Click, btnFolder_Click,btnColor_Click, btnFont_Click, btnPrint_Click};for (int i = 0; i < btnTexts.Length; i++){Button btn = new Button();btn.Text = btnTexts[i];btn.Location = new Point(50, yPos);btn.Size = new Size(150, 30);btn.Click += btnEvents[i];this.Controls.Add(btn);yPos += 40;}// 添加用于展示效果的LabelLabel displayLabel = new Label();displayLabel.Name = "displayLabel";displayLabel.Text = "效果展示区";displayLabel.Location = new Point(250, 30);displayLabel.Size = new Size(300, 200);this.Controls.Add(displayLabel);}// 1. OpenFileDialog示例private void btnOpenFile_Click(object sender, EventArgs e){OpenFileDialog openFileDialog = new OpenFileDialog();openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);openFileDialog.Filter = "文本文件|*.txt|Word文档|*.docx|所有文件|*.*";openFileDialog.Title = "选择文件";openFileDialog.Multiselect = false; // 不允许多选openFileDialog.RestoreDirectory = true;if (openFileDialog.ShowDialog() == DialogResult.OK){try{// 读取文件内容并显示string content = File.ReadAllText(openFileDialog.FileName);((Label)this.Controls["displayLabel"]).Text = $"打开的文件:{openFileDialog.FileName}\n\n内容:{content}";}catch (Exception ex){MessageBox.Show($"读取失败:{ex.Message}");}}}// 2. SaveFileDialog示例private void btnSaveFile_Click(object sender, EventArgs e){SaveFileDialog saveFileDialog = new SaveFileDialog();saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);saveFileDialog.Filter = "文本文件|*.txt|CSV文件|*.csv";saveFileDialog.Title = "保存文件";saveFileDialog.FileName = "未命名文件"; // 默认文件名saveFileDialog.OverwritePrompt = true; // 覆盖提示if (saveFileDialog.ShowDialog() == DialogResult.OK){try{// 写入示例内容string content = "这是通过SaveFileDialog保存的示例文本";File.WriteAllText(saveFileDialog.FileName, content);((Label)this.Controls["displayLabel"]).Text = $"文件已保存至:{saveFileDialog.FileName}";}catch (Exception ex){MessageBox.Show($"保存失败:{ex.Message}");}}}// 3. FolderBrowserDialog示例private void btnFolder_Click(object sender, EventArgs e){FolderBrowserDialog folderDialog = new FolderBrowserDialog();folderDialog.Description = "请选择一个文件夹(可新建)";folderDialog.RootFolder = Environment.SpecialFolder.MyComputer; // 初始位置为"此电脑"folderDialog.ShowNewFolderButton = true;if (folderDialog.ShowDialog() == DialogResult.OK){// 统计文件夹内文件数量int fileCount = Directory.GetFiles(folderDialog.SelectedPath).Length;((Label)this.Controls["displayLabel"]).Text = $"选中的文件夹:{folderDialog.SelectedPath}\n包含文件数量:{fileCount}个";}}// 4. ColorDialog示例private void btnColor_Click(object sender, EventArgs e){ColorDialog colorDialog = new ColorDialog();colorDialog.AllowFullOpen = true; // 允许自定义颜色colorDialog.FullOpen = false; // 初始不展开自定义面板colorDialog.Color = ((Label)this.Controls["displayLabel"]).ForeColor; // 初始颜色为当前文本色if (colorDialog.ShowDialog() == DialogResult.OK){// 设置文本颜色((Label)this.Controls["displayLabel"]).ForeColor = colorDialog.Color;((Label)this.Controls["displayLabel"]).Text = $"选中的颜色:{colorDialog.Color.Name}\nRGB值:({colorDialog.Color.R},{colorDialog.Color.G},{colorDialog.Color.B})";}}// 5. FontDialog示例private void btnFont_Click(object sender, EventArgs e){FontDialog fontDialog = new FontDialog();fontDialog.ShowColor = true; // 允许选择颜色fontDialog.MinSize = 8;fontDialog.MaxSize = 24;fontDialog.Font = ((Label)this.Controls["displayLabel"]).Font; // 初始字体为当前字体if (fontDialog.ShowDialog() == DialogResult.OK){// 设置字体和颜色((Label)this.Controls["displayLabel"]).Font = fontDialog.Font;((Label)this.Controls["displayLabel"]).ForeColor = fontDialog.Color;((Label)this.Controls["displayLabel"]).Text = $"选中的字体:{fontDialog.Font.Name}\n大小:{fontDialog.Font.Size}pt\n样式:{fontDialog.Font.Style}";}}// 6. PrintDialog示例private void btnPrint_Click(object sender, EventArgs e){PrintDialog printDialog = new PrintDialog();PrintDocument printDoc = new PrintDocument();// 配置打印内容(通过PrintPage事件)printDoc.PrintPage += (s, args) =>{// 打印示例文本args.Graphics.DrawString("这是打印的示例内容\n来自PrintDialog演示",new Font("宋体", 12),Brushes.Black,new PointF(100, 100));};printDialog.Document = printDoc;printDialog.AllowPrintToFile = true;printDialog.AllowSelection = false;printDialog.Copies = 1;if (printDialog.ShowDialog() == DialogResult.OK){try{printDoc.Print();((Label)this.Controls["displayLabel"]).Text = $"打印设置:\n打印机:{printDialog.PrinterSettings.PrinterName}\n份数:{printDialog.PrinterSettings.Copies}";}catch (Exception ex){MessageBox.Show($"打印失败:{ex.Message}");}}}}
}

实例说明

  1. 上述代码创建了一个 WinForm 窗口,包含 6 个按钮分别触发不同对话框,通过右侧 Label 展示操作结果。

  2. 每个对话框实例都包含了核心属性配置、异常处理(如文件读写失败)和用户反馈。

  3. 实际开发中,可根据需求简化代码(例如省略动态创建控件的部分,直接在设计器拖放按钮和 Label)。

  4. 打印对话框需注意:PrintDocumentPrintPage事件是配置打印内容的核心,示例中简化了打印逻辑,实际可打印文本、图片等复杂内容。

通过表格和实例,可快速掌握各对话框的核心用法及属性差异,便于在实际项目中灵活应用。

c#序列化

三种序列化方式对比表

序列化方式核心组件 / 库命名空间必要特性优点缺点
二进制序列化BinaryFormatterSystem.Runtime.Serialization.Formatters.Binary[Serializable]效率高(二进制传输快)、体积小不可读(无法直接查看内容)、仅限.NET 平台
JSON 序列化(原生)DataContractJsonSerializerSystem.Runtime.Serialization.Json类:[DataContract];属性:[DataMember]文本格式易读、跨平台(支持多语言)需手动标记特性、使用稍复杂
JSON 序列化(第三方)Newtonsoft.Json(推荐)Newtonsoft.Json无需标记特性、使用简单、支持复杂对象 / 集合相比二进制,体积稍大、效率略低(日常可忽略)

实例代码展示

1. 二进制序列化相关代码
// 1. 定义可序列化的类
[Serializable]  // 必须添加此特性
public class People
{public string Name { get; set; }public int Age { get; set; }public string Sex { get; set; }public string Birth { get; set; }
}
// 2. 序列化过程
public void BinarySerialize()
{People people = new People(){Name = "吴亦凡",Age = 18,Sex = "男",Birth = "2005-01-01"};// 创建文件流using (FileStream fs = new FileStream("people.bin", FileMode.Create)){BinaryFormatter bf = new BinaryFormatter();bf.Serialize(fs, people);  // 将对象写入流}
}
// 3. 反序列化过程
public void BinaryDeserialize()
{using (FileStream fs = new FileStream("people.bin", FileMode.Open)){BinaryFormatter bf = new BinaryFormatter();// 反序列化并转换为People类型People people = bf.Deserialize(fs) as People;Console.WriteLine($"姓名:{people.Name},年龄:{people.Age}");}
}
2. JSON 序列化(原生DataContractJsonSerializer)相关代码
// 1. 定义数据契约类
using System.Runtime.Serialization;[DataContract]  // 标记为数据契约类
public class People
{[DataMember]  // 标记为需序列化的成员public string Name { get; set; }[DataMember]public int Age { get; set; }[DataMember]public string Sex { get; set; }[DataMember]public string Birth { get; set; }
}
// 2. 序列化
public void JsonSerialize_Native()
{People people = new People(){Name = "吴亦凡",Age = 18,Sex = "男",Birth = "2005-01-01"};using (FileStream fs = new FileStream("people.json", FileMode.Create)){DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(People));jsonSerializer.WriteObject(fs, people);  // 写入JSON}
}
// 3. 反序列化
public void JsonDeserialize_Native()
{using (FileStream fs = new FileStream("people.json", FileMode.Open)){DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(People));People people = jsonSerializer.ReadObject(fs) as People;  // 读取JSON并转换为对象Console.WriteLine($"姓名:{people.Name},年龄:{people.Age}");}
}
3. JSON 序列化(第三方Newtonsoft.Json)相关代码
using Newtonsoft.Json;// 1. 定义普通类(无需任何特性)
public class People
{public string Name { get; set; }public int Age { get; set; }public string Sex { get; set; }public string Birth { get; set; }
}
// 2. 序列化
public void JsonSerialize_Newtonsoft()
{People people = new People(){Name = "吴亦凡",Age = 18,Sex = "男",Birth = "2005-01-01"};// 转换对象为JSON字符串string jsonStr = JsonConvert.SerializeObject(people);// 写入文件File.WriteAllText("people.json", jsonStr);
}
// 3. 反序列化
public void JsonDeserialize_Newtonsoft()
{// 读取JSON字符串string jsonStr = File.ReadAllText("people.json");// 转换为对象People people = JsonConvert.DeserializeObject<People>(jsonStr);Console.WriteLine($"姓名:{people.Name},年龄:{people.Age}");
}

XML 序列化

操作知识点整理的表格及示例代码展示:

一、XML 格式要求与核心语法总结表

类别具体内容说明示例
格式要求1. 唯一根元素(整个文档仅一个顶层元素)<Students>为根元素,所有其他元素嵌套其中
2. 标签匹配(每个开始标签必须有对应结束标签)<Student>对应</Student>,不可遗漏
3. 正确嵌套(元素不可交叉嵌套)错误:<a><b></a></b>;正确:<a><b></b></a>
4. 属性规范(值需用引号括起,同一元素属性不重复)<Version versionNum="2.1" pTime="2023-03-28">(属性值用双引号)
核心语法1. 处理指令(声明版本和编码,位于文档开头)<?xml version="1.0" encoding="utf-8" ?>
2. 元素(开始标签 + 内容 + 结束标签)<StuName>高启强</StuName>(内容为文本)
3. 属性(元素的附加信息,格式:属性名 ="值")<Version versionNum="2.1">versionNum为属性,值为 "2.1")
4. 注释(以<!--开头,-->结尾)<!-- 这是一个学生信息的XML文档 -->

二、XML 序列化与反序列化核心信息表

核心工具类所属命名空间序列化步骤反序列化步骤特点
XmlSerializerSystem.Xml.Serialization1. 定义实体类(无需特殊特性); 2. 创建FileStreamStreamWriter; 3. 实例化XmlSerializer(指定类型); 4. 调用Serialize()写入 XML; 5. 释放资源。1. 创建FileStreamStreamReader; 2. 实例化XmlSerializer(与序列化类型一致); 3. 调用Deserialize()转换为对象; 4. 释放资源。1. 生成的 XML 结构清晰,包含类型信息; 2. 支持对象与 XML 直接转换; 3. 跨平台兼容性好。

三、XmlDocument 常用操作对象与方法表

对象 / 类成员(属性 / 方法)说明
XmlDocumentLoad(string path)加载指定路径的 XML 文件(如xmlDoc.Load("XMLFile1.xml")
DocumentElement获取 XML 文档的根节点(如<Students>节点)
XmlNodeName获取节点名称(如node.Name返回 "Student")
InnerText获取节点的文本内容(如childNode.InnerText返回 "高启强")
ChildNodes获取当前节点的所有子节点(如rootNode.ChildNodes获取所有子元素)

四、XML 与 JSON 对比表(优化版)

对比维度XML 特性JSON 特性
格式风格标签式(如<Name>...</Name>),冗余较多键值对式(如"Name":""),简洁轻量
带宽占用较高(标签冗余)较低(格式简洁)
可读性结构清晰但标签繁琐更简洁,人类易读性更强
扩展性支持命名空间、注释,扩展性强不支持注释,扩展性较弱
解析工具XmlSerializerXmlDocumentDataContractJsonSerializerNewtonsoft.Json
典型应用场景配置文件(如 App.config)、WebService接口数据交互、轻量级本地存储

五、示例代码展示

1. XML 序列化与反序列化代码
using System.IO;
using System.Xml.Serialization;// 1. 定义实体类(无需特殊特性)
public class People
{public string Name { get; set; }public int Age { get; set; }public string Sex { get; set; }public string Birth { get; set; }
}
// 2. 序列化:对象 → XML
public void XmlSerialize()
{People people = new People(){Name = "吴亦凡",Age = 18,Sex = "男",Birth = "2005-01-01"};// 创建文件流和写入器(using自动释放资源)using (FileStream fs = new FileStream("people.xml", FileMode.Create))using (StreamWriter sw = new StreamWriter(fs)){// 实例化序列化器(指定目标类型)XmlSerializer serializer = new XmlSerializer(typeof(People));// 执行序列化并写入XML文件serializer.Serialize(sw, people);}
}
// 3. 反序列化:XML → 对象
public void XmlDeserialize()
{// 创建文件流和读取器using (FileStream fs = new FileStream("people.xml", FileMode.Open))using (StreamReader sr = new StreamReader(fs)){XmlSerializer serializer = new XmlSerializer(typeof(People));// 反序列化并转换为People对象People people = serializer.Deserialize(sr) as People;// 输出结果Console.WriteLine($"姓名:{people.Name},年龄:{people.Age}");}
}

生成的people.xml内容:

<?xml version="1.0" encoding="utf-8"?>
<People xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Name>吴亦凡</Name><Age>18</Age><Sex>男</Sex><Birth>2005-01-01</Birth>
</People>
2. 使用 XmlDocument 读取 XML 代码
using System.Xml;
using System.Collections.Generic;// 1. 定义学生实体类
public class Student
{public string StuName { get; set; }public int StuAge { get; set; }public string StuGender { get; set; }public string StuClass { get; set; }
}
// 2. 读取XML并转换为学生列表
private void ReadXml()
{// 创建XML文档对象XmlDocument xmlDoc = new XmlDocument();// 加载XML文件(路径需根据实际情况调整)xmlDoc.Load("XMLFile1.xml");// 获取根节点(<Students>)XmlNode rootNode = xmlDoc.DocumentElement;List<Student> students = new List<Student>();// 遍历根节点的所有子节点foreach (XmlNode node in rootNode.ChildNodes){// 只处理<Student>节点if (node.Name == "Student"){Student student = new Student();// 遍历<Student>的子节点(如<StuName>、<StuAge>)foreach (XmlNode childNode in node.ChildNodes){switch (childNode.Name){case "StuName":student.StuName = childNode.InnerText;break;case "StuAge":student.StuAge = int.Parse(childNode.InnerText);break;case "StuGender":student.StuGender = childNode.InnerText;break;case "StuClass":student.StuClass = childNode.InnerText;break;}}students.Add(student);}}// 输出读取结果foreach (var stu in students){Console.WriteLine($"姓名:{stu.StuName},年龄:{stu.StuAge},班级:{stu.StuClass}");}
}

对应的XMLFile1.xml内容:

<?xml version="1.0" encoding="utf-8" ?>
<Students><Student><StuName>高启强</StuName><StuAge>48</StuAge><StuGender>男</StuGender><StuClass>C#一班</StuClass></Student><Student><StuName>孟钰</StuName><StuAge>16</StuAge><StuGender>女</StuGender><StuClass>C#一班</StuClass></Student><DataInfo><Version versionNum="2.1" pTime="2023-03-28">数据版本信息</Version></DataInfo>
</Students>

INI 文件操作

以下是根据 INI 文件操作知识点整理的表格及示例代码展示:

一、INI 文件结构组成表

组成部分格式规范作用说明示例代码
节(Section)用方括号[]包裹,区分配置组按功能分组配置项,支持中文 / 多层级[Database][相机1]
键值对(Key-Value)键与值用等号=连接,无数据类型(均为字符串)存储具体配置项Server=127.0.0.1曝光=50
注释以分号;开头,单行注释说明配置项含义,不影响文件解析; 数据库服务器地址

二、INI 文件特点表

特点类别具体说明
格式类型纯文本文件,可直接用记事本等工具编辑,可读性强
结构复杂度仅 “节 - 键 - 值” 三层结构,简单直观,易于理解和维护
层级支持支持多节(如[Database][Logging]),可按功能分组配置
数据类型无内置数据类型,所有值均为字符串,需手动转换为 int、bool 等类型
依赖与兼容性依赖 Windows 系统kernel32.dll API,原生支持 Windows,跨平台(如 Linux)需额外库

三、C# 操作 INI 的核心 API 表

函数名所属库功能描述关键参数说明
WritePrivateProfileStringkernel32.dll向 INI 文件写入键值对lpAppName(节名)、lpKeyName(键名)、lpString(值)、lpFileName(文件路径)
GetPrivateProfileStringkernel32.dll从 INI 文件读取键对应的值lpAppName(节名)、lpKeyName(键名)、lpDefault(默认值)、lpReturnedString(结果缓冲区)、nSize(缓冲区大小)、lpFileName(文件路径)

四、操作注意事项表

注意事项具体说明
路径配置需在App.config中配置路径(如"Config.ini"),确保程序有读写权限,建议用相对路径
数据类型转换读取的值均为字符串,需手动转换(如int.Parse()bool.Parse()
系统依赖依赖 Windows 的kernel32.dll,仅支持 Windows 系统,跨平台需用其他库(如INIFileParser
缓冲区大小Read方法中StringBuilder容量(如 255)需根据值长度调整,避免截断

五、示例代码展示

1. App.config 配置 INI 文件路径
<?xml version="1.0" encoding="utf-8" ?>
<configuration><appSettings><!-- 配置INI文件路径(相对路径:程序根目录;绝对路径:如"C:\Config.ini") --><add key="InIFilePath" value="Config.ini" /></appSettings>
</configuration>
2. INI 操作工具类(FileIni.cs)
using System;
using System.Text;
using System.Runtime.InteropServices;  // 用于DllImport特性
using System.Configuration;           // 用于读取App.confignamespace _06_INI文件操作.Utility
{internal class FileIni{// 从App.config中读取INI文件路径private static string filePath = ConfigurationManager.AppSettings["InIFilePath"].ToString();// 导入kernel32.dll的WritePrivateProfileString函数(写入INI)[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]private static extern bool WritePrivateProfileString(string lpAppName,   // 节名string lpKeyName,   // 键名string lpString,    // 值string lpFileName   // INI文件路径);// 导入kernel32.dll的GetPrivateProfileString函数(读取INI)[DllImport("kernel32.dll", CharSet = CharSet.Auto)]private static extern uint GetPrivateProfileString(string lpAppName,   // 节名string lpKeyName,   // 键名string lpDefault,   // 默认值(未找到时返回)StringBuilder lpReturnedString,  // 存储结果的字符串构建器uint nSize,         // 结果缓冲区大小string lpFileName   // INI文件路径);/// <summary>/// 向INI文件写入键值对/// </summary>/// <param name="section">节名(如"Database")</param>/// <param name="key">键名(如"Server")</param>/// <param name="value">值(如"127.0.0.1")</param>public static void Write(string section, string key, string value){WritePrivateProfileString(section, key, value, filePath);}/// <summary>/// 从INI文件读取键对应的值/// </summary>/// <param name="section">节名</param>/// <param name="key">键名</param>/// <returns>键对应的值(字符串类型)</returns>public static string Read(string section, string key){StringBuilder sb = new StringBuilder(255);  // 缓冲区大小(可根据需求调整)GetPrivateProfileString(section, key, "", sb, 255, filePath);return sb.ToString();}}
}
3. 写入 INI 配置示例
// 向[相机1]节写入参数
FileIni.Write("相机1", "曝光", "50");
FileIni.Write("相机1", "亮度", "100");
FileIni.Write("相机1", "相机ip", "192.168.1.100");// 向[Database]节写入数据库配置
FileIni.Write("Database", "Server", "127.0.0.1");
FileIni.Write("Database", "Port", "3306");
FileIni.Write("Database", "Username", "root");
FileIni.Write("Database", "Password", "123456");// 向[Logging]节写入日志配置
FileIni.Write("Logging", "Level", "INFO");
FileIni.Write("Logging", "File", "/var/log/myapp.log");
4. 读取 INI 配置示例
// 读取[相机1]节的配置
string exposure = FileIni.Read("相机1", "曝光");       // 结果:"50"
string cameraIp = FileIni.Read("相机1", "相机ip");    // 结果:"192.168.1.100"// 读取[Database]节的配置
string dbServer = FileIni.Read("Database", "Server"); // 结果:"127.0.0.1"
string dbPort = FileIni.Read("Database", "Port");     // 结果:"3306"// 数据类型转换(字符串→目标类型)
int exposureValue = int.Parse(exposure);              // 转换为整数:50
int portValue = int.Parse(dbPort);                    // 转换为整数:3306// 输出结果
Console.WriteLine($"相机曝光:{exposureValue},数据库端口:{portValue}");

CSV 文件读写

以下是根据 CSV 文件读写知识点整理的表格及示例代码展示:

一、CSV 文件核心特性表

特性类别具体说明
格式类型纯文本文件,可被任何文本编辑器(记事本、Notepad++ 等)直接打开和编辑
兼容性支持 Excel、Google Sheets 等表格工具直接打开,自动转换为表格格式
结构特点无复杂标签,仅通过逗号(分隔列)换行符(分隔行) 组织数据,体积小、易传输
核心用途存储表格数据(行 - 列结构),适合简单数据交换(如报表导出、数据备份)

二、CSV 格式规则表

规则类别具体说明示例
列分隔默认用英文字符逗号(,) 分隔同一行的不同字段姓名,年龄,性别(3 列:姓名、年龄、性别)
行分隔每行代表一条记录,以换行符(\r\n 或 \n) 结束小明,20,男\r\n小红,18,女(2 条记录)
表头(可选)首行通常为表头,描述各列含义首行姓名,年龄,性别明确后续列的意义
特殊字段处理字段包含逗号、换行符等特殊字符时,需用双引号("") 包裹Doe, John需写为"Doe, John",避免被解析为 2 列

三、C# 读写 CSV 核心步骤表

操作类型核心步骤
写入 CSV1. 准备数据(如List<Student>集合); 2. 处理表头(首行写入列名); 3. 遍历数据,将对象属性用逗号拼接为行(特殊字段需用双引号包裹); 4. 通过StreamWriter写入文件(指定编码避免乱码)。
读取 CSV1. 通过StreamReader按行读取文件; 2. 跳过表头(或验证列名); 3. 每行按逗号分割为字段数组(处理双引号包裹的特殊字段); 4. 转换字段为对应数据类型,封装为对象集合。

四、注意事项表

注意事项具体说明
编码问题写入时需指定编码(如UTF8),避免中文乱码(示例:StreamWriter(filePath, false, Encoding.UTF8)
特殊字段处理字段包含逗号、引号或换行符时,必须用双引号包裹;复杂场景建议用第三方库(如CsvHelper)处理
分隔符变体部分 CSV 可能用制表符(Tab)分隔(称为 TSV),读取时需调整分割符(Split('\t')
数据类型转换读取的字段均为字符串,需手动转换为intDateTime等类型(建议用int.TryParse等安全转换)
第三方库推荐复杂场景(大量数据、嵌套字段)可使用CsvHelper(NuGet 安装)简化解析逻辑

五、CSV 与其他格式对比表

格式核心特点适用场景缺点
CSV纯文本、逗号分隔、结构简单、兼容性强简单表格数据(报表导出、Excel 交互)、轻量数据备份不支持复杂结构(如嵌套)、需手动处理特殊字段
XML标签化、支持复杂结构和注释、扩展性强配置文件、跨平台数据交换(WebService)标签冗余、体积大
JSON轻量、键值对结构、跨平台、易解析接口数据传输、轻量存储(配置、列表数据)不适合复杂表格数据直观展示
INI节 - 键 - 值结构、适合配置、Windows 友好应用程序基础配置(窗口设置、设备参数)不支持表格结构、跨平台兼容性弱

六、示例代码展示

1. 数据模型定义
// 定义学生数据模型(对应CSV的行结构)
public class Student
{public string Name { get; set; }   // 姓名(对应"姓名"列)public int Age { get; set; }       // 年龄(对应"年龄"列)public string Gender { get; set; } // 性别(对应"性别"列)
}
2. 写入 CSV 文件
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;// 写入CSV文件方法
public void WriteCsv()
{// 1. 准备数据(模拟学生列表)List<Student> students = new List<Student>{new Student { Name = "小明", Age = 20, Gender = "男" },new Student { Name = "小红", Age = 18, Gender = "女" },new Student { Name = "Doe, John", Age = 22, Gender = "男" }  // 含逗号的特殊字段};// 2. 定义CSV文件路径string filePath = "students.csv";// 3. 写入文件(指定UTF8编码避免中文乱码)using (StreamWriter sw = new StreamWriter(filePath, false, Encoding.UTF8)){// 3.1 写入表头sw.WriteLine("姓名,年龄,性别");// 3.2 写入数据行(处理特殊字段)foreach (var student in students){// 处理包含逗号的字段:用双引号包裹string name = student.Name.Contains(",") ? $"\"{student.Name}\"" : student.Name;// 拼接行(字段用逗号分隔)string line = $"{name},{student.Age},{student.Gender}";sw.WriteLine(line);}}Console.WriteLine("CSV文件写入完成!");
}

生成的students.csv内容:

姓名,年龄,性别
小明,20,男
小红,18,女
"Doe, John",22,男  # 特殊字段被双引号包裹,避免逗号被误解析
3. 读取 CSV 文件
// 读取CSV文件并转换为Student列表
public List<Student> ReadCsv()
{List<Student> students = new List<Student>();string filePath = "students.csv";// 读取文件(指定UTF8编码)using (StreamReader sr = new StreamReader(filePath, Encoding.UTF8)){// 1. 读取并跳过表头(或验证表头合法性)string header = sr.ReadLine();// 2. 逐行读取数据string line;while ((line = sr.ReadLine()) != null){// 处理带双引号的特殊字段:移除引号line = line.Replace("\"", "");// 按逗号分割为字段数组string[] fields = line.Split(',');// 验证字段数量(确保与表头列数一致)if (fields.Length != 3){Console.WriteLine($"跳过无效行:{line}");continue;}// 3. 转换字段为Student对象(安全类型转换)if (int.TryParse(fields[1], out int age)){students.Add(new Student{Name = fields[0],Age = age,Gender = fields[2]});}else{Console.WriteLine($"年龄转换失败,跳过行:{line}");}}}return students;
}// 使用示例
var studentList = ReadCsv();
foreach (var s in studentList)
{Console.WriteLine($"姓名:{s.Name},年龄:{s.Age},性别:{s.Gender}");
}

输出结果:

姓名:小明,年龄:20,性别:男
姓名:小红,年龄:18,性别:女
姓名:Doe, John,年龄:22,性别:男  # 正确解析含逗号的字段
http://www.xdnf.cn/news/1317547.html

相关文章:

  • 为何她总在关键时“失联”?—— 解密 TCP 连接异常中断
  • tcp会无限次重传吗
  • 前端vue3+后端spring boot导出数据
  • 《设计模式》工厂方法模式
  • 【CV 目标检测】Fast RCNN模型②——算法流程
  • 代码随想录算法训练营四十四天|图论part02
  • 【Luogu】每日一题——Day21. P3556 [POI 2013] MOR-Tales of seafaring (图论)
  • 上网行为组网方案
  • 数据结构03(Java)--(递归行为和递归行为时间复杂度估算,master公式)
  • Mac(五)自定义鼠标滚轮方向 LinearMouse
  • Linux软件编程:进程与线程(线程)
  • JVM学习笔记-----StringTable
  • Docker Compose 安装 Neo4j 的详细步骤
  • PostgreSQL导入mimic4
  • go基础学习笔记
  • k8s集群搭建一主多从的jenkins集群
  • Win11 文件资源管理器预览窗格显示 XAML 文件内容教程
  • C++ vector的使用
  • 10 SQL进阶-SQL优化(8.15)
  • 说一下事件委托
  • Java 大视界 -- Java 大数据分布式计算在基因测序数据分析与精准医疗中的应用(400)
  • 【UEFI系列】ACPI
  • 跨越南北的养老对话:为培养“银发中国”人才注入新动能
  • JavaScript 性能优化实战:从评估到落地的全链路指南
  • Spark03-RDD02-常用的Action算子
  • 在鸿蒙中实现深色/浅色模式切换:从原理到可运行 Demo
  • E2B是一个开源基础设施,允许您在云中安全隔离的沙盒中运行AI生成的代码和e2b.dev网站
  • Diamond基础2:开发流程之LedDemo
  • c_str()函数的详细解析
  • 简单的 VSCode 设置