C#读取文件, IO 类属性及使用示例
C#读取文件, IO 类属性及使用示例
以下是包含属性说明、带注释的使用示例的汇总表格,清晰展示各属性的功能及实际应用场景:
类名 属性(非静态) 带注释的使用示例 BinaryReader
BaseStream
// 创建文件流,用于读取二进制文件 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}"); } }
BinaryWriter
BaseStream
using (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}"); }
BufferedStream
Length
using (var fs = new FileStream("file.txt", FileMode.Open)) // 打开现有文件 using (var buffered = new BufferedStream(fs)) // 用缓冲流包装文件流(提升读写性能) { // 获取流的总长度(字节数,即文件大小) long totalBytes = buffered.Length; Console.WriteLine($"文件总大小:{totalBytes} 字节"); }
Position
using (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个字节 }
CanRead
using (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("流不可读取"); } }
CanWrite
using (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("流不可写入"); } }
BufferSize
using (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次数越多,适合大文件读写 }
DirectoryInfo
Name
// 创建目录信息实例(指向C盘的test目录) var dir = new DirectoryInfo(@"C:\test"); // 获取目录的名称(不含路径) string dirName = dir.Name; Console.WriteLine($"目录名:{dirName}"); // 输出:test
FullName
var 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 }
Exists
var dir = new DirectoryInfo(@"C:\newDir"); // 判断目录是否存在 if (!dir.Exists) { dir.Create(); // 不存在则创建目录 Console.WriteLine("目录已创建"); } else { Console.WriteLine("目录已存在"); }
CreationTime
var dir = new DirectoryInfo(@"C:\test"); // 获取目录的创建时间(本地时间) DateTime createTime = dir.CreationTime; Console.WriteLine($"创建时间:{createTime:yyyy-MM-dd HH:mm:ss}"); // 输出格式:2024-01-01 10:30:00
LastWriteTime
var dir = new DirectoryInfo(@"C:\test"); // 获取目录最后一次修改的时间(如新增/删除子文件/目录时更新) DateTime lastWrite = dir.LastWriteTime; Console.WriteLine($"最后修改时间:{lastWrite:yyyy-MM-dd HH:mm:ss}");
DriveInfo
Name
// 创建驱动器信息实例(指向C盘) var drive = new DriveInfo("C:"); // 获取驱动器名称(格式为"盘符:\") string driveName = drive.Name; Console.WriteLine($"驱动器名:{driveName}"); // 输出:C:\
DriveType
var drive = new DriveInfo("C:"); // 获取驱动器类型(Fixed为固定磁盘,Removable为可移动磁盘等) DriveType type = drive.DriveType; Console.WriteLine($"驱动器类型:{type}"); // 输出:Fixed(机械/固态硬盘)
TotalSize
var drive = new DriveInfo("C:"); // 先判断驱动器是否就绪(如U盘插入且可访问) if (drive.IsReady) { // 获取驱动器总容量(字节) long totalSize = drive.TotalSize; // 转换为GB(1GB=1024^3字节) Console.WriteLine($"总容量:{totalSize / 1024 / 1024 / 1024} GB"); }
AvailableFreeSpace
var drive = new DriveInfo("C:"); if (drive.IsReady) { // 获取驱动器可用空间(字节,用户可使用的剩余空间) long freeSpace = drive.AvailableFreeSpace; Console.WriteLine($"可用空间:{freeSpace / 1024 / 1024 / 1024} GB"); }
DriveFormat
var drive = new DriveInfo("C:"); if (drive.IsReady) { // 获取驱动器的文件系统格式(如NTFS、FAT32) string format = drive.DriveFormat; Console.WriteLine($"文件系统:{format}"); // 输出:NTFS }
IsReady
var drive = new DriveInfo("D:"); // 判断驱动器是否就绪(如光盘放入、U盘插入且挂载成功) if (drive.IsReady) { Console.WriteLine("驱动器已就绪,可访问"); } else { Console.WriteLine("驱动器未就绪(如未插入或未挂载)"); }
FileInfo
Name
// 创建文件信息实例(指向当前目录的test.txt) var file = new FileInfo("test.txt"); // 获取文件名(含扩展名,不含路径) string fileName = file.Name; Console.WriteLine($"文件名:{fileName}"); // 输出:test.txt
FullName
var file = new FileInfo("test.txt"); // 获取文件的完整路径(包含盘符、目录和文件名) string fullPath = file.FullName; Console.WriteLine($"完整路径:{fullPath}"); // 输出:C:\当前目录\test.txt
Length
var file = new FileInfo("test.txt"); // 判断文件是否存在(不存在时Length会报错) if (file.Exists) { // 获取文件大小(字节数) long fileSize = file.Length; Console.WriteLine($"文件大小:{fileSize} 字节"); }
Exists
var file = new FileInfo("temp.txt"); // 判断文件是否存在 if (file.Exists) { file.Delete(); // 存在则删除 Console.WriteLine("文件已删除"); } else { file.Create().Dispose(); // 不存在则创建 Console.WriteLine("文件已创建"); }
CreationTime
var file = new FileInfo("test.txt"); // 获取文件的创建时间 DateTime createTime = file.CreationTime; Console.WriteLine($"创建时间:{createTime:yyyy-MM-dd HH:mm:ss}");
LastWriteTime
var file = new FileInfo("test.txt"); // 获取文件最后一次修改的时间(写入内容后更新) DateTime lastWrite = file.LastWriteTime; Console.WriteLine($"最后修改时间:{lastWrite:yyyy-MM-dd HH:mm:ss}");
IsReadOnly
var file = new FileInfo("test.txt"); // 判断文件是否为只读 if (file.IsReadOnly) { Console.WriteLine("文件是只读的,修改前需取消只读"); file.IsReadOnly = false; // 取消只读属性 } // 现在可以写入文件 using (var sw = file.AppendText()) { sw.WriteLine("新增内容"); }
FileStream
Length
using (var fs = new FileStream("data.dat", FileMode.Open)) // 打开文件流 { // 获取文件总长度(字节,即文件大小) long fileLength = fs.Length; Console.WriteLine($"文件总长度:{fileLength} 字节"); }
Position
using (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); } }
Name
using (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操作 }
MemoryStream
Length
using (var ms = new MemoryStream()) // 创建内存流(数据存储在内存中) { // 向内存流写入数据 byte[] data = Encoding.UTF8.GetBytes("内存数据测试"); ms.Write(data, 0, data.Length); // 获取内存流中数据的总长度(字节) long streamLength = ms.Length; Console.WriteLine($"内存流长度:{streamLength} 字节"); // 输出:14("内存数据测试"的UTF8字节数) }
Position
using (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 }
StreamReader
BaseStream
using (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(编码的标准名称) }
EndOfStream
using (var reader = new StreamReader("log.txt")) { // 循环读取,直到流末尾(EndOfStream为true) while (!reader.EndOfStream) { string line = reader.ReadLine(); // 逐行读取 Console.WriteLine(line); } }
StreamWriter
BaseStream
using (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编码写入 }
AutoFlush
using (var writer = new StreamWriter("log.txt")) { // 设置AutoFlush为true:每次写入后自动刷新缓冲区(默认false,需手动调用Flush()或关闭流才写入) writer.AutoFlush = true; writer.WriteLine("操作1完成"); // 写入后立即刷新到文件(无需等待) writer.WriteLine("操作2完成"); // 立即刷新,确保断电等情况不丢失数据 }
表格中每个示例均通过注释解释了属性的作用、代码逻辑及注意事项(如空值判断、权限检查等),便于理解属性的实际用法和场景限制。
1. 类与属性对应表
类名 | 主要属性(非静态) | 属性描述 |
---|---|---|
BinaryReader | BaseStream | 获取当前阅读器的基础流(如 FileStream) |
BinaryWriter | BaseStream | 获取当前写入器的基础流(如 FileStream) |
BufferedStream | Length 、Position 、CanRead 、CanWrite 、BufferSize | 流长度、当前位置、是否可读写、缓冲区大小 |
DirectoryInfo | Name 、FullName 、Parent 、Exists 、CreationTime 、LastWriteTime | 目录名、完整路径、父目录、是否存在、创建时间、最后写入时间 |
DriveInfo | Name 、DriveType 、TotalSize 、AvailableFreeSpace 、DriveFormat 、IsReady | 驱动器名(如 "C:")、驱动器类型、总容量、可用空间、文件系统、是否就绪 |
FileInfo | Name 、FullName 、Length 、Exists 、CreationTime 、LastWriteTime 、IsReadOnly | 文件名、完整路径、文件大小(字节)、是否存在、创建时间、最后写入时间、是否只读 |
FileStream | Length 、Position 、CanRead 、CanWrite 、Name 、IsAsync | 流长度、当前位置、是否可读写、关联文件名、是否异步操作 |
MemoryStream | Length 、Position 、Capacity 、ToArray() (方法,常作为属性使用) | 流长度、当前位置、容量(可分配的内存大小)、转换为字节数组 |
StreamReader | BaseStream 、CurrentEncoding 、EndOfStream | 基础流、当前编码(如 UTF8)、是否到达流末尾 |
StreamWriter | BaseStream 、Encoding 、AutoFlush | 基础流、写入编码、是否自动刷新缓冲区 |
2. 属性使用示例表(C# 语法)
类名 | 属性名 | 使用示例代码 | 代码说明 |
---|---|---|---|
BinaryReader | BaseStream | var reader = new BinaryReader(File.Open("data.bin", FileMode.Open)); | 创建 BinaryReader 实例,关联文件流 |
Stream baseStream = reader.BaseStream; | 获取阅读器的基础流(如 FileStream) | ||
BinaryWriter | BaseStream | var writer = new BinaryWriter(File.Open("data.bin", FileMode.Create)); | 创建 BinaryWriter 实例,关联文件流 |
Stream baseStream = writer.BaseStream; | 获取写入器的基础流(如 FileStream) | ||
BufferedStream | Length | var bufferStream = new BufferedStream(File.Open("file.txt", FileMode.Open)); | 创建缓冲流实例 |
long length = bufferStream.Length; | 获取缓冲流的总长度(字节数) | ||
Position | long pos = bufferStream.Position; | 获取当前在流中的位置(字节偏移量) | |
CanRead | bool canRead = bufferStream.CanRead; | 判断缓冲流是否支持读取操作 | |
CanWrite | bool canWrite = bufferStream.CanWrite; | 判断缓冲流是否支持写入操作 | |
BufferSize | int bufferSize = bufferStream.BufferSize; | 获取缓冲区的大小(字节数) | |
DirectoryInfo | Name | var dir = new DirectoryInfo(@"C:\test"); | 创建目录信息实例 |
string name = dir.Name; | 获取目录名(如 "test",不含路径) | ||
FullName | string fullPath = dir.FullName; | 获取目录的完整路径(如 "C:\test") | |
Parent | DirectoryInfo parent = dir.Parent; | 获取父目录的 DirectoryInfo 实例 | |
Exists | bool exists = dir.Exists; | 判断目录是否实际存在 | |
CreationTime | DateTime createTime = dir.CreationTime; | 获取目录的创建时间(本地时间) | |
LastWriteTime | DateTime lastWrite = dir.LastWriteTime; | 获取目录最后被修改的时间(本地时间) | |
DriveInfo | Name | var drive = new DriveInfo("C:"); | 创建驱动器信息实例 |
string driveName = drive.Name; | 获取驱动器名(如 "C:") | ||
DriveType | DriveType type = drive.DriveType; | 获取驱动器类型(如 Fixed (固定磁盘)、Removable (可移动设备)) | |
TotalSize | long totalSize = drive.TotalSize; | 获取驱动器总容量(字节,需驱动器就绪) | |
AvailableFreeSpace | long freeSpace = drive.AvailableFreeSpace; | 获取驱动器可用空间(字节,需驱动器就绪) | |
DriveFormat | string format = drive.DriveFormat; | 获取文件系统格式(如 NTFS、FAT32,需驱动器就绪) | |
IsReady | bool isReady = drive.IsReady; | 判断驱动器是否就绪(可访问,如 U 盘是否插入) | |
FileInfo | Name | var file = new FileInfo("document.txt"); | 创建文件信息实例 |
string fileName = file.Name; | 获取文件名(如 "document.txt",不含路径) | ||
FullName | string fullPath = file.FullName; | 获取文件的完整路径 | |
Length | long fileSize = file.Length; | 获取文件大小(字节数,文件需存在) | |
Exists | bool exists = file.Exists; | 判断文件是否实际存在 | |
CreationTime | DateTime createTime = file.CreationTime; | 获取文件的创建时间(本地时间) | |
LastWriteTime | DateTime lastWrite = file.LastWriteTime; | 获取文件最后被修改的时间(本地时间) | |
IsReadOnly | bool isReadOnly = file.IsReadOnly; | 判断文件是否设置了只读属性 | |
FileStream | Length | using (var fs = new FileStream("data.dat", FileMode.Open)) | 创建文件流实例(using 确保自动释放资源) |
long length = fs.Length; | 获取文件流的总长度(字节数) | ||
Position | long pos = fs.Position; | 获取当前在文件流中的位置(字节偏移量) | |
CanRead | bool canRead = fs.CanRead; | 判断文件流是否支持读取操作 | |
CanWrite | bool canWrite = fs.CanWrite; | 判断文件流是否支持写入操作 | |
Name | string name = fs.Name; | 获取文件流关联的文件名(含路径) | |
IsAsync | bool isAsync = fs.IsAsync; | 判断文件流是否为异步操作模式(构造时指定) | |
MemoryStream | Length | var ms = new MemoryStream(); | 创建内存流实例 |
long length = ms.Length; | 获取内存流中已写入数据的长度(字节) | ||
Position | long pos = ms.Position; | 获取当前在内存流中的位置(字节偏移量) | |
Capacity | int capacity = ms.Capacity; | 获取内存流的容量(可容纳的最大字节数,可动态扩展) | |
ToArray() | byte[] data = ms.ToArray(); | 将内存流中的数据转换为字节数组(常用作属性使用) | |
StreamReader | BaseStream | using (var sr = new StreamReader("text.txt")) | 创建流读取器实例(默认 UTF8 编码) |
Stream baseStream = sr.BaseStream; | 获取读取器的基础流(如 FileStream) | ||
CurrentEncoding | Encoding encoding = sr.CurrentEncoding; | 获取当前使用的文本编码(如 UTF8) | |
EndOfStream | bool isEnd = sr.EndOfStream; | 判断是否已到达流的末尾(是否还有可读取内容) | |
StreamWriter | BaseStream | using (var sw = new StreamWriter("output.txt")) | 创建流写入器实例(默认 UTF8 编码) |
Stream baseStream = sw.BaseStream; | 获取写入器的基础流(如 FileStream) | ||
Encoding | Encoding encoding = sw.Encoding; | 获取写入时使用的文本编码 | |
AutoFlush | bool autoFlush = sw.AutoFlush; | 判断是否启用自动刷新(每次写入后自动刷新缓冲区到基础流) |
注释说明
示例代码均基于.NET Framework/.NET Core 的
System.IO
命名空间,使用前需导入该命名空间(using System.IO;
)。涉及文件操作的类(如
FileStream
、StreamReader
)建议使用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.ASCII | 7 位 ASCII 编码,仅支持字符 0-127(超出范围会替换为? ) |
Encoding.UTF8 | UTF-8 编码(可变长度,1-4 字节表示一个字符),兼容 ASCII,支持全球字符 | |
Encoding.Unicode | UTF-16 编码(小端序,2 字节表示大部分字符,特殊字符用 4 字节) | |
Encoding.BigEndianUnicode | UTF-16 编码(大端序,字节顺序与Unicode 相反) | |
Encoding.UTF32 | UTF-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) | 计算将字节数组解码为字符所需的字符数 | |
主要派生类 | ASCIIEncoding | Encoding.ASCII 的具体实现,仅支持 ASCII 字符 |
UTF8Encoding | Encoding.UTF8 的具体实现,可通过构造函数指定是否包含 BOM(字节顺序标记) 示例:new UTF8Encoding(encoderShouldEmitUTF8Identifier: true) (带 BOM) | |
UnicodeEncoding | Encoding.Unicode 的具体实现(小端序 UTF-16) | |
UTF32Encoding | Encoding.UTF32 的具体实现 | |
注意事项 | 编码与解码一致性 | 编码和解码必须使用相同的编码格式,否则会出现乱码 |
BOM(字节顺序标记) | UTF-8/UTF-16 等可能包含 BOM(如 UTF-8 的 BOM 为0xEF,0xBB,0xBF ),用于标识编码类型,需根据场景决定是否保留 | |
Default 编码的风险 | 依赖系统环境,跨平台(如 Windows 与 Linux)使用可能导致编码不一致,建议显式指定编码(如 UTF8) | |
异常处理 | 解码无效字节时默认替换为� ,可通过DecoderFallback 自定义错误处理逻辑 |
总结
Encoding
类是 C# 中处理字符与字节转换的核心类,通过预定义的静态属性(如UTF8
)可快速使用常见编码,核心方法GetBytes
和GetString
实现基本的编码 / 解码操作。实际开发中应优先使用 UTF-8 等跨平台编码,避免依赖Default
编码,并注意编码和解码的一致性以防止乱码。
以下是 C# 中Encoding
类的知识点分析及代码示例表格,包含核心用法、常见场景及注意事项:
知识点分类 | 具体内容 / API | 代码示例 | 示例说明 |
---|---|---|---|
基础信息 | 命名空间 | using System.Text; | 必须导入该命名空间才能使用Encoding 类及其派生类 |
核心功能 | - | 实现字符与字节的相互转换(编码:char→byte;解码:byte→char) | |
常用静态编码 | Encoding.ASCII | byte[] asciiBytes = Encoding.ASCII.GetBytes("A±"); | ASCII 仅支持 0-127 字符,超出范围(如 "±")会被替换为? ,结果为[65, 63] |
Encoding.UTF8 | byte[] utf8Bytes = Encoding.UTF8.GetBytes("你好"); | UTF-8 编码中 "你好" 占 6 字节(每个汉字 3 字节),结果为[228,189,160,229,165,189] | |
Encoding.Unicode | byte[] unicodeBytes = Encoding.Unicode.GetBytes("A"); | UTF-16(小端序)中 "A" 占 2 字节,结果为[65, 0] | |
Encoding.BigEndianUnicode | byte[] beBytes = Encoding.BigEndianUnicode.GetBytes("A"); | UTF-16(大端序)中 "A" 占 2 字节,结果为[0, 65] | |
Encoding.UTF32 | byte[] 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); | 用于大字节流分批解码,提升性能 |
关键说明:
编码一致性:编码(
GetBytes
)和解码(GetString
)必须使用同一种编码格式,否则必然出现乱码。BOM 作用:字节顺序标记(BOM)用于标识编码类型(如 UTF-8 的 BOM),但在跨系统传输时可能需要移除(如 HTTP 协议通常不需要 BOM)。
异常处理:可通过
EncoderFallback
和DecoderFallback
自定义无效字符 / 字节的处理逻辑(如抛出异常而非默认替换)。推荐编码:优先使用
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 | 关闭后是否还原原目录 | bool | true |
扩展属性 | |||
Multiselect | 是否允许选择多个文件 | bool | true (多选时用FileNames 数组) |
2. SaveFileDialog(文件保存对话框)
属性名称 | 作用描述 | 数据类型 | 示例值 |
---|---|---|---|
核心属性 | (与 OpenFileDialog 基本一致) | ||
FileName | 获取用户输入的保存文件路径 | string | "C:\\导出\\数据.csv" |
Filter | 限制保存文件类型 | string | "Excel 文件| *.xlsx | 所有文件 | *.*" |
OverwritePrompt | 若文件已存在,是否提示覆盖 | bool | true (默认值) |
3. FolderBrowserDialog(文件夹选择对话框)
属性名称 | 作用描述 | 数据类型 | 示例值 |
---|---|---|---|
核心属性 | |||
SelectedPath | 获取选中的文件夹路径 | string | "D:\\项目\\素材" |
Description | 对话框内的描述文本(标题下方) | string | "请选择存放备份的文件夹" |
特有属性 | |||
ShowNewFolderButton | 是否显示 "新建文件夹" 按钮 | bool | true |
RootFolder | 初始浏览的根目录(系统特殊文件夹) | Environment.SpecialFolder | Environment.SpecialFolder.Desktop (桌面) |
4. ColorDialog(颜色对话框)
属性名称 | 作用描述 | 数据类型 | 示例值 |
---|---|---|---|
核心属性 | |||
Color | 获取用户选中的颜色 | System.Drawing.Color | Color.Red 、Color.FromArgb(255,0,0) |
特有属性 | |||
AllowFullOpen | 是否允许打开自定义颜色面板 | bool | false (禁用自定义) |
FullOpen | 打开时是否直接显示自定义颜色面板 | bool | true |
SolidColorOnly | 是否只允许选择纯色(禁用渐变色) | bool | true |
5. FontDialog(字体对话框)
属性名称 | 作用描述 | 数据类型 | 示例值 |
---|---|---|---|
核心属性 | |||
Font | 获取选中的字体(含名称 / 大小 / 样式) | System.Drawing.Font | new Font("微软雅黑",12,FontStyle.Bold) |
扩展属性 | |||
ShowColor | 是否允许选择字体颜色 | bool | true |
MinSize /MaxSize | 限制可选字体的最小 / 最大尺寸 | float | 8 (最小 8 号字) |
6. PrintDialog(打印对话框)
属性名称 | 作用描述 | 数据类型 | 示例值 |
---|---|---|---|
核心属性 | |||
PrinterSettings | 获取打印设置(打印机 / 份数 / 范围等) | PrinterSettings | PrinterSettings.PrinterName (打印机名称) |
Document | 关联需要打印的文档对象 | PrintDocument | new PrintDocument() |
特有属性 | |||
AllowPrintToFile | 是否允许 "打印到文件" | bool | true |
AllowSelection | 是否允许打印选中内容 | bool | true |
Copies | 设置打印份数 | short | 2 (打印 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}");}}}} }
实例说明
上述代码创建了一个 WinForm 窗口,包含 6 个按钮分别触发不同对话框,通过右侧 Label 展示操作结果。
每个对话框实例都包含了核心属性配置、异常处理(如文件读写失败)和用户反馈。
实际开发中,可根据需求简化代码(例如省略动态创建控件的部分,直接在设计器拖放按钮和 Label)。
打印对话框需注意:
PrintDocument
的PrintPage
事件是配置打印内容的核心,示例中简化了打印逻辑,实际可打印文本、图片等复杂内容。
通过表格和实例,可快速掌握各对话框的核心用法及属性差异,便于在实际项目中灵活应用。
c#序列化
三种序列化方式对比表
序列化方式 | 核心组件 / 库 | 命名空间 | 必要特性 | 优点 | 缺点 |
---|---|---|---|---|---|
二进制序列化 | BinaryFormatter | System.Runtime.Serialization.Formatters.Binary | [Serializable] | 效率高(二进制传输快)、体积小 | 不可读(无法直接查看内容)、仅限.NET 平台 |
JSON 序列化(原生) | DataContractJsonSerializer | System.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 序列化与反序列化核心信息表
核心工具类 | 所属命名空间 | 序列化步骤 | 反序列化步骤 | 特点 |
---|---|---|---|---|
XmlSerializer | System.Xml.Serialization | 1. 定义实体类(无需特殊特性); 2. 创建FileStream 和StreamWriter ; 3. 实例化XmlSerializer (指定类型); 4. 调用Serialize() 写入 XML; 5. 释放资源。 | 1. 创建FileStream 和StreamReader ; 2. 实例化XmlSerializer (与序列化类型一致); 3. 调用Deserialize() 转换为对象; 4. 释放资源。 | 1. 生成的 XML 结构清晰,包含类型信息; 2. 支持对象与 XML 直接转换; 3. 跨平台兼容性好。 |
三、XmlDocument 常用操作对象与方法表
对象 / 类 | 成员(属性 / 方法) | 说明 |
---|---|---|
XmlDocument | Load(string path) | 加载指定路径的 XML 文件(如xmlDoc.Load("XMLFile1.xml") ) |
DocumentElement | 获取 XML 文档的根节点(如<Students> 节点) | |
XmlNode | Name | 获取节点名称(如node.Name 返回 "Student") |
InnerText | 获取节点的文本内容(如childNode.InnerText 返回 "高启强") | |
ChildNodes | 获取当前节点的所有子节点(如rootNode.ChildNodes 获取所有子元素) |
四、XML 与 JSON 对比表(优化版)
对比维度 | XML 特性 | JSON 特性 |
---|---|---|
格式风格 | 标签式(如<Name>...</Name> ),冗余较多 | 键值对式(如"Name":"" ),简洁轻量 |
带宽占用 | 较高(标签冗余) | 较低(格式简洁) |
可读性 | 结构清晰但标签繁琐 | 更简洁,人类易读性更强 |
扩展性 | 支持命名空间、注释,扩展性强 | 不支持注释,扩展性较弱 |
解析工具 | XmlSerializer 、XmlDocument 等 | DataContractJsonSerializer 、Newtonsoft.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 表
函数名 | 所属库 | 功能描述 | 关键参数说明 |
---|---|---|---|
WritePrivateProfileString | kernel32.dll | 向 INI 文件写入键值对 | lpAppName (节名)、lpKeyName (键名)、lpString (值)、lpFileName (文件路径) |
GetPrivateProfileString | kernel32.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 核心步骤表
操作类型 | 核心步骤 |
---|---|
写入 CSV | 1. 准备数据(如List<Student> 集合); 2. 处理表头(首行写入列名); 3. 遍历数据,将对象属性用逗号拼接为行(特殊字段需用双引号包裹); 4. 通过StreamWriter 写入文件(指定编码避免乱码)。 |
读取 CSV | 1. 通过StreamReader 按行读取文件; 2. 跳过表头(或验证列名); 3. 每行按逗号分割为字段数组(处理双引号包裹的特殊字段); 4. 转换字段为对应数据类型,封装为对象集合。 |
四、注意事项表
注意事项 | 具体说明 |
---|---|
编码问题 | 写入时需指定编码(如UTF8 ),避免中文乱码(示例:StreamWriter(filePath, false, Encoding.UTF8) ) |
特殊字段处理 | 字段包含逗号、引号或换行符时,必须用双引号包裹;复杂场景建议用第三方库(如CsvHelper )处理 |
分隔符变体 | 部分 CSV 可能用制表符(Tab)分隔(称为 TSV),读取时需调整分割符(Split('\t') ) |
数据类型转换 | 读取的字段均为字符串,需手动转换为int 、DateTime 等类型(建议用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,性别:男 # 正确解析含逗号的字段