零、文章目录
IO详解
1、IO是什么
(1)IO是什么
- IO是输入/输出的缩写,即Input/Output。在计算机领域,IO通常指数据在内部存储器和外部存储器或其他周边设备之间的输入和输出。输入和输出是信息处理系统(例如计算器)与外部世界(可能是人类或另一信息处理系统)之间的通信。输入是系统接收的信号或数据,输出则是从其发送的信号或数据。
(2)C#中的IO
- 在C#中,IO(输入/输出)主要涉及文件和流的读写操作。目录和文件操作以及序列化和反序列化。
- 相关的类,结构,委托和枚举都在System.IO命名空间下。
2、System.IO命名空间
System.IO
命名空间由IO相关的类,结构,委托和枚举组成。这些类可用于将数据读取和写入文件或数据流。它还包含用于文件和目录支持的类。
(1)System.IO命名空间类
类名 | 描述 |
---|---|
BinaryReader | 它用于读取原始数据类型作为指定编码中的二进制值。 |
BinaryWriter | 它用于将二进制中的原始类型写入流。 |
BufferedStream | 它用于添加缓冲层来读取和写入另一个流的操作。这是一个密封类,其它类不继承此类。 |
Directory | 处理文件夹的静态类。 |
DirectoryInfo | 它用于公开通过目录和子目录创建,移动和枚举的实例方法。这是一个密封类,其它类不继承此类。 |
DirectoryNotFoundException | 它用于处理与文件或目录无关的异常。 |
DriveInfo | 它用于访问驱动器上的信息。 |
DriveNotFoundException | 它用于处理驱动器找不到的异常。 |
EndOfStreamException | 它用于处理流终止的异常。 |
ErrorEventArgs | 它为FileSystemWatcher.Error 事件提供数据。 |
File | 处理文件的静态类。 |
FileFormatException | 它用于处理文件格式的异常。 |
FileInfo | 它用于提供用于创建,复制,删除,移动和打开文件的属性和实例方法。 |
FileLoadException | 它用于处理文件加载异常。 |
FileNotFoundException | 它用于处理文件找不到异常。 |
FileStream | 它提供一个文件流,支持同步和异步读写操作。 |
FileSystemEventArgs | 它提供目录事件的数据。 |
FileSystemInfo | 它为FileInfo 和DirectoryInfo 对象提供基类。 |
FileSystemWatcher | 它会监听文件系统更改通知,并在目录中的目录或文件中引发事件更改。 |
InternalBufferOverflowException | 此类用于处理内部缓冲区溢出异常。 |
InvalidDataException | 它用于处理无效数据异常。 |
IODescriptionAttribute | 它设置视觉设计器在引用事件,扩展器或属性时可以显示的描述。 |
IOException | 它是处理I/O错误的异常类。 |
MemoryStream | 它用于创建一个其后备存储是内存的流。 |
Path | 处理路径的静态类。 |
PathTooLongException | 它是一个异常类,用于处理路径太长的异常。 |
PipeException | 这个异常类用于处理与管道相关的异常。 |
RenamedEventArgs | 它用于为“重命名”事件提供数据。 |
Stream | 它用于提供字节序列的通用视图。这是一个抽象类。 |
StreamReader | 它用于实现从字节流读取字符的TextReader 类。 |
StringReader | 它用于实现从字符串读取的TextReader 类。 |
StringWriter | 它用于实现一个TextWriter 类,用于将信息写入字符串。 信息存储在一个基础的StringBuilder 中。 |
TextReader | 此类用于表示可以读取一系列连续字符的读取器。 |
TextWriter | 此类用于表示可以编写一系列连续字符的写入器。 |
UnmanagedMemoryAccessor | 它用于从托管代码提供对非托管内存块的随机访问。 |
UnmanagedMemoryStream | 它用于从托管代码访问非托管内存块。 |
(2)System.IO命名空间结构
结构 | 描述 |
---|---|
WaitForChangedResult | 它包含有关发生变化的信息。 |
(3)System.IO命名空间委托
委托 | 描述 |
---|---|
ErrorEventHandler | 它表示处理FileSystemWatcher 对象Error 事件的方法。 |
FileSystemEventHandler | 它表示处理FileSystemWatcher 类的已更改,创建或已删除事件的方法。 |
RenamedEventHandler | 它表示将处理FileSystemWatcher 类的重命名事件的方法。 |
(4)System.IO命名空间枚举
枚举 | 描述 |
---|---|
DriveType | 它用于定义驱动器类型的常量,包括:CDROM,固定,网络等。 |
FileAccess | 它用于定义对文件进行读取,写入或读取/写入访问的常量。 |
FileAttributes | 它用于提供文件和目录的属性。 |
FileMode | 它用于指定操作系统应如何打开文件。 |
FileOptions | 它用于表示创建FileStream 对象的高级选项。 |
FileShare | 它用于包含用于控制其他FileStream 对象可以对同一文件进行访问的类型的常量。 |
HandleInheritability | 它指定底层句柄是否可由子进程继承。 |
NotifyFilters | 它用于监视指定要在文件或文件夹中的更改。 |
SearchOption | 它用于指定是搜索当前目录还是当前目录以及所有子目录。 |
SeekOrigin | 它用于指定要用于搜索的流中的位置。 |
WatcherChangeTypes | 文件或目录可能会发生更改。 |
- FileMode:枚举类型,用来设定文件的打开方式,可选值如下:
- Append:打开一个已有的文件,并将光标放置在文件的末尾。如果文件不存在,则创建文件;
- Create:创建一个新的文件,如果文件已存在,则将旧文件删除,然后创建新文件;
- CreateNew:创建一个新的文件,如果文件已存在,则抛出异常;
- Open:打开一个已有的文件,如果文件不存在,则抛出异常;
- OpenOrCreate:打开一个已有的文件,如果文件不存在,则创建一个新的文件并打开;
- Truncate:打开一个已有的文件,然后将文件清空(删除原有内容),如果文件不存在,则抛出异常。
- FileAccess:枚举类型,用来设置文件的存取
- Read
- ReadWrite
- Write
- FileShare:枚举类型,用来设置文件的权限,可选值如下:
- Inheritable:允许子进程继承文件句柄,Win32 不直接支持此功能;
- None:在文件关闭前拒绝共享当前文件,打开该文件的任何请求(由此进程或另一进程发出的请求)都将失败;
- Read:允许随后打开文件读取,如果未指定此标志,则文件关闭前,任何打开该文件以进行读取的请求都将失败,需要注意的是,即使指定了此标志,仍需要附加权限才能够访问该文件;
- ReadWrite:允许随后打开文件读取或写入,如果未指定此标志,则文件关闭前,任何打开该文件以进行读取或写入的请求都将失败,需要注意的是,即使指定了此标志,仍需要附加权限才能够访问该文件;
- Write:允许随后打开文件写入,如果未指定此标志,则文件关闭前,任何打开该文件以进行写入的请求都将失败,需要注意的是,即使指定了此标志,仍可能需要附加权限才能够访问该文件;
- Delete:允许随后删除文件。
(5)System.IO分类归纳
- 文件系统操作:File、Path、Directory、FileSystemInfo、FileInfo、DirectoryInfo、DriveInfo,FileSystemWatcher
- 流:Stream、BufferedStream、MemoryStream、UnmanagedMemoryStream、FileStream
- 读写器:TextReader、TextWriter、StreamReader、StreamWriter、StringReader、StringWriter,BinaryReader、BinaryWriter
- IO枚举:FileAccess、FileAttributes、FileOptions、FileShare、FileMode、SearchOption、SeekOrigin、DriveType
- IO异常:IOException、FileLoadException、DriveNotFoundException、FileNotFoundException、DirectoryNotFoundException、PathTooLongException、EndOfStreamException
3、公共知识
(1)托管资源和非托管资源
- 托管资源是由CLR(Common Language Runtime)管理分配和释放的资源,通常是托管内存,由垃圾回收器自动进行回收,不需要人工干预。
- 非托管资源则是.NET不知道如何回收的资源,常见的一类非托管资源是包装操作系统资源的对象,如文件、窗口、网络连接、数据库连接、画刷、图标等。这类资源在垃圾回收器清理时会被调用Object.Finalize()方法,对于非托管对象,需要在此方法中编写回收非托管资源的代码,以便垃圾回收器正确回收资源。
(2)using的作用
- 它可以实现在一个代码块中自动释放非托管资源,这通常是通过在using()中创建变量并初始化,然后using结束时自动释放这些资源。
- using也可以用于引入外部代码库或模块,将这些代码与原有代码进行组合,以实现更高级别的功能。它让代码更加灵活和易于维护。
//using结束自动释放资源,释放占用的文件
using (StreamReader reader = new StreamReader("data.txt"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
(3)相对路径和绝对路径
-
相对路径和绝对路径是文件路径的两种表示方式。
-
绝对路径是从盘符开始的路径,例如
C:\windows\system32\cmd.exe
。 -
相对路径则是从当前路径开始的路径。例如,如果当前路径为
C:\windows
,要描述上述路径,只需输入system32\cmd.exe
。实际上,严格的相对路径写法应为.\system32\cmd.exe
,其中.
表示当前路径。..
可以表示上层路径。
4、目录和文件操作
- 目录和文件操作主要类:File、Path、Directory、FileSystemInfo、FileInfo、DirectoryInfo、DriveInfo、FileSystemWatcher
File、Directory、Path
:它们都是静态的工具类,用于操作文件、目录和路径。DirectoryInfo、FileInfo
:都继承于抽象基类FileSystemInfo
,它们都是密封类,无法继承。DriveInfo
:也是密封类,无法继承,但是它不是继承于FileSystemInfo
,而是object
。FileSystemWatcher
:用于监控文件变化的类。
(1)File
-
处理文件的静态类。
-
常用方法
-
Create(string path)
:创建指定路径的新文件。 -
ReadAllText(string path)
:读取指定路径的文件的全部文本内容。 -
ReadLines(string path)
:按行读取指定路径的文件的文本内容。 -
WriteAllText(string path, string contents)
:将指定的文本内容写入到指定的文件中。 -
AppendAllText(string path, string contents)
:将指定的文本内容追加到指定的文件中。 -
Delete(string path)
:删除指定的文件。 -
Move(string sourceFileName, string destFileName)
:将指定的文件移动到新位置。 -
Copy(string sourceFileName, string destFileName)
:将指定的文件复制到新位置。 -
Exists(string path)
:检查指定的文件是否存在。 -
GetLastWriteTime(string path)
:获取指定文件的最后写入时间。 -
GetAttributes(string path)
:获取指定文件的属性信息。
-
-
代码演示
Console.WriteLine("创建新文件,文件默认是打开的,需要手工关闭,否则写入会报占用异常");
FileStream fs = File.Create("example.txt");
fs.Close();
Console.WriteLine("写入文本到文件中");
File.WriteAllText("example.txt", "Hello, World!");
Console.WriteLine("读取文件内容");
Console.WriteLine(File.ReadAllText("example.txt"));
Console.WriteLine("追加文件内容");
File.AppendAllText("example.txt", "This is append content.");
Console.WriteLine(File.ReadAllText("example.txt"));
Console.WriteLine("检查文件是否存在");
Console.WriteLine("File exists: " + File.Exists("example.txt"));
Console.WriteLine("获取文件的最后写入时间");
Console.WriteLine("Last write time: " + File.GetLastWriteTime("example.txt"));
Console.WriteLine("移动文件");
File.Move("example.txt", "newexample.txt");
Console.WriteLine("复制文件");
File.Copy("newexample.txt", "example.txt");
Console.WriteLine("删除文件");
File.Delete("example.txt");
File.Delete("newexample.txt");
(2)Path
- 处理路径的静态类。
- 常用方法
GetFullPath(string path)
:此方法用于获取完全合格的路径。它接受一个相对路径作为输入,并返回一个完全合格的路径。GetTempFileName()
:此方法用于生成一个包含随机字母和数字的临时文件,并返回该文件的完全合格的路径。GetRandomFileName()
:此方法用于返回一个包含随机字母和数字的文件名。Combine(string path1, string path2)
: 此方法将两个或更多的路径组合在一起。它接受两个或更多的字符串参数,所有的这些参数都会被加入到返回的路径中。GetDirectoryName(string path)
: 返回指定路径的目录信息。GetExtension(string path)
: 这个方法用于获取文件的扩展名。它接受一个路径作为输入,然后返回该文件的扩展名。GetFileName(string path)
: 返回指定路径的文件名和扩展名。GetFileNameWithoutExtension(string path)
: 返回指定路径的文件名(不包括扩展名)。GetPathRoot(string path)
: 返回指定路径的根目录信息。
- 代码演示
Console.WriteLine("输入相对路径,返回完整路径");
Console.WriteLine(Path.GetFullPath("example.txt"));
Console.WriteLine("生成临时文件,返回完成路径");
Console.WriteLine(Path.GetTempFileName());//C:\Users\Administrator\AppData\Local\Temp\tmpBBC9.tmp
Console.WriteLine("返回随机的文件名");
Console.WriteLine(Path.GetRandomFileName());//iknagpqs.wrx
Console.WriteLine("组合路径");
string combinedPath = Path.Combine("C:\\", "Documents");
Console.WriteLine(combinedPath); //C:\Documents
Console.WriteLine("返回指定路径的目录信息");
Console.WriteLine(Path.GetDirectoryName(Path.GetFullPath("example.txt")));
Console.WriteLine("获取文件扩展名");
Console.WriteLine(Path.GetExtension("example.txt"));//.txt
Console.WriteLine("获取文件名");
Console.WriteLine(Path.GetFileName("example.txt"));//example.txt
Console.WriteLine("获取文件名(不包括扩展名)");
Console.WriteLine(Path.GetFileNameWithoutExtension("example.txt"));//example
Console.WriteLine("获取根目录");
Console.WriteLine(Path.GetPathRoot(Path.GetFullPath("example.txt")));//E:\
(3)Directory
- 处理文件夹的静态类。
- 常用方法
GetCurrentDirectory()
:获取当前路径CreateDirectory(string dir)
:创建新目录。Exists(string dir)
:检查一个目录是否存在。GetLastWriteTime(string path)
:获取目录最后修改时间GetFiles(string dir)
:获取目录下的所有文件。GetFiles(string dir, string searchPattern)
:获取目录下的符合匹配规则的文件。GetDirectories(string dir)
:获取目录下的所有子目录。Directory.GetDirectories(string dir, string searchPattern)
:获取目录下的符合匹配规则的子目录。Move(string dir)
:将一个目录移动到另一个位置。Copy(string dir)
:将一个目录复制到另一个位置。Delete(string dir)
:空目录直接删除。Delete(string dir, bool recursive)
:非空目录递归删除。
- 代码演示
Console.WriteLine("获取当前完整目录");
Console.WriteLine(Directory.GetCurrentDirectory());
Console.WriteLine("创建目录,存在的就跳过");
Console.WriteLine(Directory.CreateDirectory("D:\\path\\directory"));
Console.WriteLine("判断目录是否存在");
Console.WriteLine(Directory.Exists("D:\\path\\directory"));
Console.WriteLine("获取目录最后修改时间");
Console.WriteLine(Directory.GetLastWriteTime("D:\\path\\directory"));
Console.WriteLine("获取目录下的所有文件");
string[] files = Directory.GetFiles("D:\\");
foreach (string file in files)
{
Console.WriteLine(file);
}
Console.WriteLine("获取目录下的所有文件,匹配查找");
string[] files2 = Directory.GetFiles("D:\\","*.txt");
foreach (string file in files2)
{
Console.WriteLine(file);
}
Console.WriteLine("获取目录下的所有目录");
string[] directories = Directory.GetDirectories("D:\\");
foreach (string directory in directories)
{
Console.WriteLine(directory);
}
Console.WriteLine("获取目录下的所有目录,匹配查找");
string[] directories2 = Directory.GetDirectories("D:\\","*360*");
foreach (string directory in directories2)
{
Console.WriteLine(directory);
}
Console.WriteLine("移动目录");
Directory.CreateDirectory("D:\\A");
Directory.Move("D:\\A", "D:\\B");
Console.WriteLine("空目录直接删除");
Directory.Delete("D:\\B");
Console.WriteLine("非空目录递归删除");
Directory.Delete("D:\\path", true);
(4)FileSystemInfo
FileSystemInfo
是 .NET 中的一个抽象基类,它提供了一些用于获取文件系统信息的方法和属性。这些属性和方法可以在派生类(如FileInfo
和DirectoryInfo
)中使用,以提供更具体的文件系统操作。- 常用属性
LinkTarget
:快捷方式或者符号链接指向的地址。CreationTime
: 获取文件或目录的创建时间。LastAccessTime
: 获取文件或目录最后一次访问的时间。LastWriteTime
: 获取文件或目录最后一次修改的时间。FullName
: 获取文件或目录的完整路径。Name
: 获取文件或目录的名称。Extension
: 获取文件的扩展名。Attributes
: 获取文件或目录的属性(如只读、隐藏等)。Exists
:文件或目录是否存在。
- 常用方法
Delete()
: 删除文件或目录。Refresh()
: 刷新对象的状态。CreateAsSymbolicLink(string pathToTarget)
:创建符号链接指向目表地址ResolveLinkTarget(bool returnFinalTarget)
:解析符号链接的目标,这个方法返回一个FileSystemInfo
对象,表示符号链接指向的实际文件或目录。GetObjectData(SerializationInfo info, StreamingContext context)
:用于将FileSystemInfo
对象的数据序列化为一个SerializationInfo
对象,并将其存储在一个StreamingContext
对象中。这个方法通常用于在 .NET 中进行对象的序列化操作。
(5)FileInfo
-
处理文件的类,是
FileSystemInfo
的子类。 -
常用属性
IsReadOnly
:是否只读。Length
:文件的大小(以字节为单位)。DirectoryName
:目录名称。Directory
:包含该文件的目录的DirectoryInfo
对象。
-
常用方法
Create()
:创建一个新文件并返回一个FileStream
对象。Open(FileMode mode)
:用于打开一个文件,并返回一个FileStream
对象,以便进行读取、写入或其他操作。Open(FileMode mode, FileAccess access)
:用于打开一个文件,并返回一个FileStream
对象,以便进行读取、写入或其他操作。Open(FileMode mode, FileAccess access, FileShare share)
:用于打开一个文件,并返回一个FileStream
对象,以便进行读取、写入或其他操作。Open(FileStreamOptions options)
:用于打开一个文件,并返回一个FileStream
对象,以便进行读取、写入或其他操作。AppendText()
:打开一个文件将文本追加到文件的末尾,并返回一个StreamWriter
对象。CreateText()
:创建或打开一个文本文件,并返回一个StreamWriter
对象。OpenText()
:打开一个文本文件,并返回一个StreamReader
对象。Encrypt()
:用于加密文件,以便只有特定的用户或帐户才能访问。仅在windows平台受支持。Decrypt()
:用于解密被特定帐户加密的文件。仅在windows平台受支持。CopyTo(string destFileName)
:将文件从一个位置复制到另一个位置。CopyTo(string destFileName, bool overwrite)
:将文件从一个位置复制到另一个位置,可以覆盖存在的文件。MoveTo(string destFileName)
:将文件从一个位置移动到另一个位置。MoveTo(string destFileName, bool overwrite)
:将文件从一个位置移动到另一个位置,可以覆盖。Replace(string destinationFileName, string? destinationBackupFileName)
:替换文件,destinationBackupFileName可以设置为null即不备份被替换文件。Replace(string destinationFileName, string? destinationBackupFileName, bool ignoreMetadataErrors)
:替换文件,destinationBackupFileName可以设置为null即不备份被替换文件,可以忽略元素据错误。
-
代码演示
Console.WriteLine("创建文件");
Directory.CreateDirectory("D:\\path\\");//创建了文件夹才能创建里面的文件
FileInfo fileInfo = new FileInfo("D:\\path\\test.txt");
FileStream fs = fileInfo.Create();
fs.Close();
//继承自FileSystemInfo
Console.WriteLine("文件属性");
Console.WriteLine("快捷方式或者符号链接指向的地址:" + fileInfo.LinkTarget);
Console.WriteLine("创建时间:" + fileInfo.CreationTime);
Console.WriteLine("最后访问时间:" + fileInfo.LastAccessTime);
Console.WriteLine("最后修改时间:" + fileInfo.LastWriteTime);
Console.WriteLine("完整名称:" + fileInfo.FullName);
Console.WriteLine("名称:" + fileInfo.Name);
Console.WriteLine("扩展名:" + fileInfo.Extension);
Console.WriteLine("属性:" + fileInfo.Attributes);
Console.WriteLine("是否存在:" + fileInfo.Exists);
//FileInfo特有
Console.WriteLine("是否只读:" + fileInfo.IsReadOnly);
Console.WriteLine("大小(以字节为单位):" + fileInfo.Length);
Console.WriteLine("目录名称:" + fileInfo.DirectoryName);
Console.WriteLine("目录对象:" + fileInfo.Directory);
Console.WriteLine("打开文件");
using (FileStream fileStream = fileInfo.Open(FileMode.Open))
{
// 在这里执行对文件的读取或其他操作
// 当 using 块结束时,FileStream 对象会自动关闭并释放资源。
}
using (FileStream fileStream = fileInfo.Open(FileMode.Open, FileAccess.Read))
{
// 在这里执行对文件的读取或其他操作
// 当 using 块结束时,FileStream 对象会自动关闭并释放资源。
}
using (FileStream fileStream = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
{
// 在这里执行对文件的读取或其他操作
// 当 using 块结束时,FileStream 对象会自动关闭并释放资源。
}
FileStreamOptions ops = new FileStreamOptions();
ops.Mode=FileMode.Open;
ops.Access=FileAccess.Read;
ops.Share=FileShare.Read;
using (FileStream fileStream = fileInfo.Open(ops))
{
// 在这里执行对文件的读取或其他操作
// 当 using 块结束时,FileStream 对象会自动关闭并释放资源。
}
Console.WriteLine("打开一个文件将文本追加到文件的末尾");
using (StreamWriter writer = fileInfo.AppendText())
{
writer.WriteLine("打开一个文件将文本追加到文件的末尾");
}
Console.WriteLine("创建或打开一个文本文件");
FileInfo fileInfo2 = new FileInfo("D:\\path\\test2.txt");
using (StreamWriter writer = fileInfo2.CreateText())
{
writer.WriteLine("创建或打开一个文本文件");
}
Console.WriteLine("打开一个文本文件");
using (StreamReader reader = fileInfo.OpenText())
{
// 在这里执行对文本文件的读取或写入操作
string line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
Console.WriteLine("加密文件");
fileInfo.Encrypt();
Console.WriteLine("解密文件");
fileInfo.Decrypt();
Console.WriteLine("将文件从一个位置复制到另一个位置");
fileInfo.CopyTo("D:\\path\\test3.txt");//test test2 test3
Console.WriteLine("将文件从一个位置复制到另一个位置,可以覆盖");
fileInfo.CopyTo("D:\\path\\test2.txt",true);//test test2 test3
Console.WriteLine("将文件从一个位置移动到另一个位置");
fileInfo.MoveTo("D:\\path\\test4.txt");//test2 test3 test4
Console.WriteLine("将文件从一个位置移动到另一个位置,可以覆盖");
FileInfo fileInfo3 = new FileInfo("D:\\path\\test3.txt");
fileInfo3.MoveTo("D:\\path\\test4.txt", true);//test2 test4
Console.WriteLine("替换文件");
FileInfo fileInfo4 = new FileInfo("D:\\path\\test4.txt");
fileInfo4.Replace("D:\\path\\test2.txt",null,true);//test2
Console.WriteLine("删除文件");
FileInfo fileInfo5 = new FileInfo("D:\\path\\test2.txt");
fileInfo5.Delete();
Directory.Delete("D:\\path\\");
(6)DirectoryInfo
-
处理目录的类,是
FileSystemInfo
的子类。 -
常用属性
Parent
:父目录。Root
:根目录。
-
常用方法
Create()
:创建目录。CreateSubdirectory(string path)
:在目录基础上创建子目录。EnumerateDirectories()
:路径下的所有子路径。EnumerateDirectories(string searchPattern)
:路径下的匹配的子路径。EnumerateDirectories(string searchPattern, EnumerationOptions enumerationOptions)
:路径下的匹配的子路径。EnumerateDirectories(string searchPattern, SearchOption searchOption)
:路径下的匹配的子路径。EnumerateFiles()
:路径下的所有子文件。EnumerateFiles(string searchPattern)
:路径下的匹配的子文件。EnumerateFiles(string searchPattern, EnumerationOptions enumerationOptions)
:路径下的匹配的子文件。EnumerateFiles(string searchPattern, SearchOption searchOption)
:路径下的匹配的子文件。EnumerateFileSystemInfos()
:路径下的所有子文件或路径。EnumerateFileSystemInfos(string searchPattern)
:路径下的匹配的子文件或路径。EnumerateFileSystemInfos(string searchPattern, EnumerationOptions enumerationOptions)
:路径下的匹配的子文件或路径。EnumerateFileSystemInfos(string searchPattern, SearchOption searchOption)
:路径下的匹配的子文件或路径。GetDirectories()
:路径下的所有子路径。GetDirectories(string searchPattern)
:路径下的匹配的子路径。GetDirectories(string searchPattern, SearchOption searchOption)
:路径下的匹配的子路径。GetDirectories(string searchPattern, EnumerationOptions enumerationOptions)
:路径下的匹配的子路径。GetFiles()
:路径下的所有子文件。GetFiles(string searchPattern)
:路径下的匹配的子文件。GetFiles(string searchPattern, SearchOption searchOption)
:路径下的匹配的子文件。GetFiles(string searchPattern, EnumerationOptions enumerationOptions)
:路径下的匹配的子文件。GetFileSystemInfos()
:路径下的所有子文件或路径。GetFileSystemInfos(string searchPattern)
:路径下的匹配的子文件或路径。GetFileSystemInfos(string searchPattern, SearchOption searchOption)
:路径下的匹配的子文件或路径。GetFileSystemInfos(string searchPattern, EnumerationOptions enumerationOptions)
:路径下的匹配的子文件或路径。MoveTo(string destDirName)
:移动到新目录。Delete(bool recursive)
:递归删除。
-
代码演示
Console.WriteLine("创建目录");
DirectoryInfo directoryInfo = new DirectoryInfo("D:\\path\\");
directoryInfo.Create();
//继承自FileSystemInfo
Console.WriteLine("目录属性");
Console.WriteLine("快捷方式或者符号链接指向的地址:" + directoryInfo.LinkTarget);
Console.WriteLine("创建时间:" + directoryInfo.CreationTime);
Console.WriteLine("最后访问时间:" + directoryInfo.LastAccessTime);
Console.WriteLine("最后修改时间:" + directoryInfo.LastWriteTime);
Console.WriteLine("完整名称:" + directoryInfo.FullName);
Console.WriteLine("名称:" + directoryInfo.Name);
Console.WriteLine("扩展名:" + directoryInfo.Extension);
Console.WriteLine("属性:" + directoryInfo.Attributes);
Console.WriteLine("是否存在:" + directoryInfo.Exists);
//DirectoryInfo特有
Console.WriteLine("父目录:" + directoryInfo.Parent);
Console.WriteLine("根目录:" + directoryInfo.Root);
Console.WriteLine("在目录基础上创建子目录");
directoryInfo.CreateSubdirectory("subpath");
directoryInfo.CreateSubdirectory("subpath2");
directoryInfo.CreateSubdirectory("subpath3");
directoryInfo.CreateSubdirectory("sub3");
Console.WriteLine("遍历匹配的子路径,一边遍历一边加载");
DirectoryInfo directoryInfo2 = new DirectoryInfo("D:\\");
foreach (var d in directoryInfo2.EnumerateDirectories("*360*"))
{
Console.WriteLine(d);
}
Console.WriteLine("遍历匹配的子文件,一边遍历一边加载");
foreach (var d in directoryInfo2.EnumerateFiles())
{
Console.WriteLine(d);
}
Console.WriteLine("遍历匹配的子文件或路径,一边遍历一边加载");
foreach (var d in directoryInfo2.EnumerateFileSystemInfos())
{
Console.WriteLine(d);
}
Console.WriteLine("遍历匹配的子路径,加载完开始遍历");
foreach (var d in directoryInfo2.GetDirectories("*360*"))
{
Console.WriteLine(d);
}
Console.WriteLine("遍历匹配的子文件,加载完开始遍历");
foreach (var d in directoryInfo2.GetFiles())
{
Console.WriteLine(d);
}
Console.WriteLine("遍历匹配的子文件或路径,加载完开始遍历");
foreach (var d in directoryInfo2.GetFileSystemInfos())
{
Console.WriteLine(d);
}
Console.WriteLine("递归删除目录");
directoryInfo.Delete(true);
(7)DriveInfo
-
文件系统驱动器的类。
-
常用属性:
AvailableFreeSpace
:可用空闲空间。DriveFormat
:驱动器格式。DriveType
:驱动器类型,例如,是否为网络驱动器、固定的硬盘驱动器等等。IsReady
:检查驱动器是否已经准备好进行读/写操作Name
: 驱动器的名称。RootDirectory
: 驱动器的根目录。TotalFreeSpace
: 驱动器上的可用总字节数。TotalSize
:驱动器上的总字节数。VolumeLabel
:卷标签。
-
常用方法:
GetDrives()
: 返回一个包含所有可用驱动器的数组。静态方法。
-
代码演示
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo drive in drives)
{
Console.WriteLine("驱动器的名称:" + drive.Name+"***********************************************");
Console.WriteLine("可用空闲空间:" + drive.AvailableFreeSpace);
Console.WriteLine("驱动器格式:" + drive.DriveFormat);
Console.WriteLine("驱动器类型:" + drive.DriveType + " bytes");
Console.WriteLine("检查驱动器是否已经准备好进行读/写操作: " + drive.IsReady);
Console.WriteLine("驱动器的根目录:" + drive.RootDirectory);
Console.WriteLine("驱动器上的可用总字节数:" + drive.TotalFreeSpace);
Console.WriteLine("驱动器上的总字节数:" + drive.TotalSize);
Console.WriteLine("卷标签:" + drive.VolumeLabel);
}
(8)FileSystemWatcher
- 用于监视文件或目录的更改的类。
- 代码演示-监控的文件夹要先创建存在
using System.IO;
using System.Reflection;
namespace MyIO
{
internal class Program
{
static void Main(string[] args)
{
#region FileSystemWatcher
//监控单个文件夹
{
// 创建一个新的 FileSystemWatcher
FileSystemWatcher watcher = new FileSystemWatcher();
// 指定要监视的目录
watcher.Path = @"D:\Directory";
// 订阅触发事件
watcher.NotifyFilter = NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.FileName
| NotifyFilters.DirectoryName;
// 默认 监控所有文件
watcher.Filter = "*.*";
//绑定处理函数
watcher.Changed += OnChanged;//文件或目录变化
watcher.Created += OnChanged;//文件或目录创建
watcher.Deleted += OnChanged;//文件或目录删除
watcher.Renamed += OnRenamed;//文件或目录重命名
// 开始监视
watcher.EnableRaisingEvents = true;
}
//监控多个文件夹
{
string[] directoriesToWatch = { @"D:\Directory1", @"D:\Directory2", @"D:\Directory3" };
FileSystemWatcher[] watchers = new FileSystemWatcher[directoriesToWatch.Length];
for (int i = 0; i < directoriesToWatch.Length; i++)
{
watchers[i] = new FileSystemWatcher();
watchers[i].Path = directoriesToWatch[i];
watchers[i].NotifyFilter = NotifyFilters.LastAccess| NotifyFilters.LastWrite| NotifyFilters.FileName| NotifyFilters.DirectoryName;
watchers[i].Filter = "*.*";
watchers[i].Changed += OnChanged;
watchers[i].Created += OnChanged;
watchers[i].Deleted += OnChanged;
watchers[i].Renamed += OnRenamed;
watchers[i].EnableRaisingEvents = true;
}
}
#endregion
Console.ReadKey();
}
private static void OnChanged(object source, FileSystemEventArgs e) => Console.WriteLine($"File or directory {e.FullPath} was {e.ChangeType}");
private static void OnRenamed(object source, RenamedEventArgs e) => Console.WriteLine($"File: {e.OldName} renamed to {e.Name}");
}
}
5、读写数据
- 读写主要类:TextReader、TextWriter、StreamReader、StreamWriter、StringReader、StringWriter,BinaryReader、BinaryWriter
TextReader
:是读取字符数据的抽象基类,是StreamReader
和StringReader
的基类。TextWriter
:是写入字符数据的抽象基类,是StreamWriter
和StringWriter
的基类。BinaryReader
:用特定的编码从一个输入流中读取二进制数据,默认是UTF-8编码。BinaryWriter
:用特定编码以二进制格式向输出流中写入简单数据类型,默认是UTF-8编码。
(1)流的概念
Stream
:是所有流的抽象基类。流是字节序列的抽象概念,例如文件、输入/输出设备、内部进程通信管道或者 TCP/IP 套接字。流涉及三个基本操作:读、写、查找。FileStream
:代表了能够访问一个文件 的IO流。FileStream 对输入输出进行缓冲,从而提高性能。FileStream 对象支持使用 Seek 方法对文件进行随机访问。文件使用完之后必须确保调用FileStream的Dispose方法,特别是在磁盘空间有限的环境中。BufferedStream
:给另一流上的读写操作添加一个缓冲层。它是密封类,无法继承。缓冲区可提高读取和写入性能。使用缓冲区可进行读取或写入,但不能同时进行这两种操作。MemoryStream
:创建支持存储区为内存的流。MemoryStream 封装以无符号字节数组形式存储的数据,该数组在创建 MemoryStream 对象时被初始化,或者该数组可创建为空数组。可在内存中直接访问这些封装的数据。UnmanagedMemoryStream
:提供从托管代码访问非托管内存块的能力。
(2)FileStream
Console.WriteLine("FileStream写入文件");
using (FileStream fsr = File.Create("input.txt"))//不存在创建,存在覆盖
{
byte[] bytes = Encoding.UTF8.GetBytes("1234567890");
fsr.Write(bytes, 0, bytes.Length);
fsr.Flush();//写入磁盘
}
using (FileStream fileStream = File.Create("input.txt"))//不存在创建,存在覆盖
{
StreamWriter sw = new StreamWriter(fileStream);
sw.WriteLine("12345678");
sw.Flush();
}
(3)StreamWriter和StreamReader
StreamWriter
:它的主要功能是将文本写入到流中
,例如文件流或网络流。这个类允许使用多种编码方式对文本进行编码,例如UTF-8、Unicode等。StreamReader
:它的主要用途是从流
中读取字符,这样就可以从文件或者其他输入流中读取字符。
Console.WriteLine("StreamWriter写入文件");
using (StreamWriter sw = File.AppendText("input.txt"))//追加文本
{
sw.WriteLine("1234567");
sw.Flush();
}
using (StreamWriter sw = File.AppendText("input.txt"))//追加文本
{
byte[] bytes = Encoding.Default.GetBytes("123456");
sw.BaseStream.Write(bytes, 0, bytes.Length);
sw.Flush();
}
Console.WriteLine("StreamWriter和StreamReader读写FileStream");
using (FileStream fsInput = new FileStream("input.txt", FileMode.OpenOrCreate, FileAccess.Read))
using (StreamReader sr = new StreamReader(fsInput))
using (FileStream fsOutput = new FileStream("output.txt", FileMode.OpenOrCreate, FileAccess.Write))
using (StreamWriter sw = new StreamWriter(fsOutput))
{
string line;
while ((line = sr.ReadLine()) != null)
{
// 在这里进行数据处理,例如将文本转换为大写
string processedLine = line.ToUpper();
sw.WriteLine(processedLine);
}
}
Console.WriteLine("StreamWriter和StreamReader读写FileStream,简化写法");
using (StreamReader sr = new StreamReader("input.txt", new FileStreamOptions() { Mode = FileMode.OpenOrCreate, Access = FileAccess.Read }))
using (StreamWriter sw = new StreamWriter("output.txt", new FileStreamOptions() { Mode = FileMode.OpenOrCreate, Access = FileAccess.Write }))
{
string line;
while ((line = sr.ReadLine()) != null)
{
// 在这里进行数据处理,例如将文本转换为大写
string processedLine = line.ToUpper();
sw.WriteLine(processedLine);
}
}
Console.WriteLine("StreamWriter和StreamReader读写BufferedStream");
using (BufferedStream bsInput = new BufferedStream(new FileStream("input.txt", FileMode.OpenOrCreate, FileAccess.Read)))
using (StreamReader sr = new StreamReader(bsInput))
using (BufferedStream bsOutput = new BufferedStream(new FileStream("output.txt", FileMode.OpenOrCreate, FileAccess.Write)))
using (StreamWriter sw = new StreamWriter(bsOutput))
{
string line;
while ((line = sr.ReadLine()) != null)
{
// 在这里进行数据处理,例如将文本转换为大写
string processedLine = line.ToUpper();
sw.WriteLine(processedLine);
}
}
Console.WriteLine("StreamWriter和StreamReader读写MemoryStream");
List<string> lines = new List<string>() { "First line", "Second line", "Third line" };
using (MemoryStream ms = new MemoryStream())
using (StreamWriter sw = new StreamWriter(ms))
{
//写入MemoryStream
foreach (string line in lines)
{
sw.WriteLine(line);
}
}
using (MemoryStream ms = new MemoryStream())
using (StreamReader sr = new StreamReader(ms))
{
//读取MemoryStream
ms.Position = 0;//设置读取位置从0开始
string line;
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
(4)StringWriter和StringReader
StringWriter
:它的主要功能是将文本写入到字符串中
。这个类的输出可以通过ToString()方法获取,也可以通过GetStringBuilder()方法获取一个StringBuilder对象,对字符串进行进一步的处理。StringReader
:它的主要用途是从字符串
中读取字符。
Console.WriteLine("StringWriter和StringReader读写字符串");
using (StringWriter sw = new StringWriter())
{
sw.Write("Hello, world!");
string output = sw.ToString();
}
string input = "This is a test string";
using (StringReader sr = new StringReader(input))
{
string line;
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
(5)BinaryWriter和BinaryReader
BinaryReader
:用特定的编码从一个输入流中读取二进制数据,默认是UTF-8编码。BinaryWriter
:用特定编码以二进制格式向输出流中写入简单数据类型,默认是UTF-8编码。
if (File.Exists("data.bin")) File.Delete("data.bin");
using (FileStream stream = new FileStream("data.bin", FileMode.Create))
{
// 创建一个BinaryWriter对象
BinaryWriter writer = new BinaryWriter(stream);
// 写入两个整数和一个字符串到文件中
writer.Write(123);
writer.Write(456);
writer.Write("Hello, world!");
// 关闭Writer对象
writer.Close();
}
using (FileStream stream = new FileStream("data.bin", FileMode.Open))
{
// 创建一个BinaryReader对象
BinaryReader reader = new BinaryReader(stream);
// 读取文件中的数据
int num1 = reader.ReadInt32();
int num2 = reader.ReadInt32();
string str = reader.ReadString();
// 输出读取到的数据
Console.WriteLine(num1);
Console.WriteLine(num2);
Console.WriteLine(str);
// 关闭Reader对象
reader.Close();
}
(6)大文件读写优化
- 使用BufferedStream类:BufferedStream类提供了一个缓冲区,可以将数据块读入缓冲区中,然后逐块地读写文件,从而减少磁盘I/O操作的次数,提高读写效率。
using (FileStream fs = new FileStream("largefile.txt", FileMode.OpenOrCreate))
{
using (BufferedStream bs = new BufferedStream(fs))
{
byte[] buffer = new byte[1024 * 1024]; // 1MB的缓冲区
int bytesRead;
while ((bytesRead = bs.Read(buffer, 0, buffer.Length)) != 0)
{
// 处理读入的数据,例如输出到控制台
Console.Write(Encoding.UTF8.GetString(buffer));
}
}
}
- 分块读取文件:分块读取文件是将文件分成多个块,每次读取一个块的数据进行处理。这种方法可以减少内存占用,避免读取整个文件时出现的内存溢出问题。
using (FileStream fs = new FileStream("largefile.txt", FileMode.Open))
{
byte[] buffer = new byte[1024 * 1024]; // 1MB的块大小
int bytesRead;
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) != 0)
{
// 处理读入的数据,例如输出到控制台
Console.Write(Encoding.UTF8.GetString(buffer));
}
}
- 使用StreamReader和StreamWriter类进行文本文件的读写:对于文本文件,可以使用StreamReader和StreamWriter类来进行读写操作。它们提供了按行读写文本文件的方法,非常方便。
using (FileStream fs = new FileStream("largefile.txt", FileMode.Open))
{
using (StreamWriter sw = new StreamWriter(fs))
{
sw.WriteLine("Hello World!"); // 写入一行文本
sw.Flush(); // 刷新缓冲区,将数据写入文件
}
}
using (FileStream fs = new FileStream("largefile.txt", FileMode.Open))
{
using (StreamReader sr = new StreamReader(fs))
{
string line;
while ((line = sr.ReadLine()) != null)
{
// 处理读取的文本行,例如输出到控制台
Console.WriteLine(line);
}
}
}
6、递归获取文件夹、文件
namespace MyIO
{
public class FileHepler
{
/// <summary>
/// 获取路径下的所有文件夹
/// </summary>
/// <param name="rootPath"></param>
/// <returns></returns>
public static List<DirectoryInfo> GetAllDirectorys(string rootPath)
{
if (!Directory.Exists(rootPath))
return new List<DirectoryInfo>();
List<DirectoryInfo> directoryList = new List<DirectoryInfo>();//容器
DirectoryInfo directory = new DirectoryInfo(rootPath);//root文件夹
directoryList.Add(directory);
return GetChildDirectorys(directoryList, directory);
}
/// <summary>
/// 递归获取子文件夹
/// </summary>
/// <param name="directoryList"></param>
/// <param name="directoryCurrent"></param>
/// <returns></returns>
private static List<DirectoryInfo> GetChildDirectorys(List<DirectoryInfo> directoryList, DirectoryInfo directoryCurrent)
{
var childDirectorys = directoryCurrent.GetDirectories();
if (childDirectorys != null && childDirectorys.Length > 0)
{
directoryList.AddRange(childDirectorys);
foreach (var child in childDirectorys)
{
GetChildDirectorys(directoryList, child);
}
}
return directoryList;
}
/// <summary>
/// 获取路径下的所有文件
/// </summary>
/// <param name="rootPath"></param>
/// <returns></returns>
public static List<FileInfo> GetAllFiles(string rootPath)
{
if (!Directory.Exists(rootPath))
return new List<FileInfo>();
List<FileInfo> fileList = new List<FileInfo>();//容器
DirectoryInfo directory = new DirectoryInfo(rootPath);//root文件夹
return GetChildFiles(fileList, directory);
}
/// <summary>
/// 递归获取子文件夹的文件
/// </summary>
/// <param name="fileList"></param>
/// <param name="directoryCurrent"></param>
/// <returns></returns>
private static List<FileInfo> GetChildFiles(List<FileInfo> fileList, DirectoryInfo directoryCurrent)
{
//添加文件
var childFiles= directoryCurrent.GetFiles();
if (childFiles != null && childFiles.Length > 0)
{
fileList.AddRange(childFiles);
}
//递归遍历文件夹
var childDirectorys = directoryCurrent.GetDirectories();
if (childDirectorys != null && childDirectorys.Length > 0)
{
foreach (var child in childDirectorys)
{
GetChildFiles(fileList, child);
}
}
return fileList;
}
}
}
7、实现日志打印帮助类
namespace MyIO
{
public class LogHelper
{
private static readonly int maxFileSize = 1024 * 5; // 文件最大大小为5KB
public static void Log(string message)
{
string logFilePath = $"{DateTime.Now.ToString("yyyyMMdd")}.log"; // 日志文件路径 按照日期命名
// 判断日志文件是否存在,不存在则创建
if (!File.Exists(logFilePath))
{
File.Create(logFilePath).Dispose();
}
// 计算当前日志文件的大小
FileInfo fileInfo = new FileInfo(logFilePath);
long fileSize = fileInfo.Length;
// 如果日志文件大小超过最大值,则切割文件
if (fileSize > maxFileSize)
{
string[] files = Directory.GetFiles(".\\", DateTime.Now.ToString("yyyyMMdd") + "*");
// 构造新文件名
string newFileName = string.Format("{0}_{1}.log", DateTime.Now.ToString("yyyyMMdd"), files.Length+1);
// 移动当前日志文件到新文件名
File.Move(logFilePath, newFileName);
// 重新创建空日志文件
File.Create(logFilePath).Dispose();
}
// 写入日志信息
using (StreamWriter writer = new StreamWriter(logFilePath, true))
{
writer.WriteLine(DateTime.Now.ToString() + ":" + message);
}
}
}
}