C#高级--IO详解

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 它为FileInfoDirectoryInfo对象提供基类。
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也可以用于引入外部代码库或模块,将这些代码与原有代码进行组合,以实现更高级别的功能。它让代码更加灵活和易于维护。
C# 复制代码
//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):获取指定文件的属性信息。

  • 代码演示

C# 复制代码
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): 返回指定路径的根目录信息。
  • 代码演示
C# 复制代码
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):非空目录递归删除。
  • 代码演示
C# 复制代码
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 中的一个抽象基类,它提供了一些用于获取文件系统信息的方法和属性。这些属性和方法可以在派生类(如 FileInfoDirectoryInfo)中使用,以提供更具体的文件系统操作。
  • 常用属性
    • 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即不备份被替换文件,可以忽略元素据错误。
  • 代码演示

C# 复制代码
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):递归删除。
  • 代码演示

C# 复制代码
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(): 返回一个包含所有可用驱动器的数组。静态方法。
  • 代码演示

C# 复制代码
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

  • 用于监视文件或目录的更改的类。
  • 代码演示-监控的文件夹要先创建存在
C# 复制代码
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:是读取字符数据的抽象基类,是StreamReaderStringReader的基类。
    • TextWriter:是写入字符数据的抽象基类,是StreamWriterStringWriter的基类。
    • BinaryReader:用特定的编码从一个输入流中读取二进制数据,默认是UTF-8编码。
    • BinaryWriter:用特定编码以二进制格式向输出流中写入简单数据类型,默认是UTF-8编码。

(1)流的概念

  • Stream:是所有流的抽象基类。流是字节序列的抽象概念,例如文件、输入/输出设备、内部进程通信管道或者 TCP/IP 套接字。流涉及三个基本操作:读、写、查找。
  • FileStream:代表了能够访问一个文件 的IO流。FileStream 对输入输出进行缓冲,从而提高性能。FileStream 对象支持使用 Seek 方法对文件进行随机访问。文件使用完之后必须确保调用FileStream的Dispose方法,特别是在磁盘空间有限的环境中。
  • BufferedStream:给另一流上的读写操作添加一个缓冲层。它是密封类,无法继承。缓冲区可提高读取和写入性能。使用缓冲区可进行读取或写入,但不能同时进行这两种操作。
  • MemoryStream:创建支持存储区为内存的流。MemoryStream 封装以无符号字节数组形式存储的数据,该数组在创建 MemoryStream 对象时被初始化,或者该数组可创建为空数组。可在内存中直接访问这些封装的数据。
  • UnmanagedMemoryStream:提供从托管代码访问非托管内存块的能力。

(2)FileStream

C# 复制代码
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:它的主要用途是从中读取字符,这样就可以从文件或者其他输入流中读取字符。
c# 复制代码
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:它的主要用途是从字符串中读取字符。
C# 复制代码
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编码。
C# 复制代码
 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)大文件读写优化

  1. 使用BufferedStream类:BufferedStream类提供了一个缓冲区,可以将数据块读入缓冲区中,然后逐块地读写文件,从而减少磁盘I/O操作的次数,提高读写效率。
C# 复制代码
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));
        }
    }
}
  1. 分块读取文件:分块读取文件是将文件分成多个块,每次读取一个块的数据进行处理。这种方法可以减少内存占用,避免读取整个文件时出现的内存溢出问题。
C# 复制代码
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));
    }
}
  1. 使用StreamReader和StreamWriter类进行文本文件的读写:对于文本文件,可以使用StreamReader和StreamWriter类来进行读写操作。它们提供了按行读写文本文件的方法,非常方便。
C# 复制代码
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、递归获取文件夹、文件

C# 复制代码
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、实现日志打印帮助类

C# 复制代码
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);
            }
        }
    }
}
相关推荐
尘浮生1 小时前
Java项目实战II基于SpringBoot的共享单车管理系统开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·微信小程序·小程序
huaxiaorong1 小时前
如何将旧的Android手机改造为家用服务器
后端
2401_857439691 小时前
社团管理新工具:SpringBoot框架
java·spring boot·后端
2401_857610031 小时前
Spring Boot OA:企业办公自动化的创新之路
spring boot·后端·mfc
难念的码1 小时前
Skill 语言语法基础
人工智能·后端
逸风尊者2 小时前
开发也能看懂的大模型:FNN
人工智能·后端·算法
2401_854391082 小时前
Spring Boot OA:企业数字化转型的利器
java·spring boot·后端
山山而川粤2 小时前
废品买卖回收管理系统|Java|SSM|Vue| 前后端分离
java·开发语言·后端·学习·mysql
2301_811274312 小时前
基于Spring Boot的同城宠物照看系统的设计与实现
spring boot·后端·宠物
2301_811274313 小时前
springboot嗨玩旅游网站
spring boot·后端·旅游