【C#基础】C# 文件与IO

序号 系列文章
9 【C# 基础】C# 异常处理操作
10 【C#基础】C# 正则表达式
11 【C#基础】C# 预处理器指令

文章目录

  • 前言
  • 1,文件和IO的概念
  • 2,文本文件操作
    • 2.1 File 类
    • 2.2 FileInfo 类
    • 2.3 FileStream 类
    • 2.4 StreamReader 类
    • 2.5 StreamWriter 类
      • FileStream 和 StreamReader、StreamWriter 的区别:
  • 3,二进制文件操作
    • 3.1 BinaryReader 类
    • 3.2 BinaryWriter 类
  • 4,文件目录操作
    • 4.1 Directory 类
    • 4.2 DirectoryInfo类
  • 结语

前言

☀️ 大家好,我是writer桑,前面一章已经学习了 C# 中预处理器指令的使用,那本章就开始学习 C# 程序中的文件与IO,希望看完大家能够有所收获,感谢支持!


1,文件和IO的概念

文件是以计算机硬盘为载体存储在计算机上的信息集合。在 C# 程序中,文件读写存储可以是文本文件和二进制文件。

IO 分别表示 input 和 output, 也就是输入和输出的意思。文件IO操作就是读写文件操作。当对文件进行读写时,程序中会形成一个,流是对IO设备操作的字节序列封装。输入流和输出流是最常用的两个流操作,分别用于读取文件数据(读操作)和写入文件数据(写操作)。

2,文本文件操作

文本文件操作也就是对文件进行读、写、保存等操作。在 C# 程序中,文本文件的操作有几个类可以做到,其中包括 File、FileInfo、FileStream 和 StreamReader 等类。

2.1 File 类

File 类偏向于执行一些典型的操作,其中包括复制、移动、重命名、创建、打开、删除和追加文本内容。同时,File 类还提供了获取和设置与创建、访问和写入文件相关的文件属性或 DateTime 信息。

下表列出了 File 类中一些常用的方法:

方法名称 描述
AppendAllLines(String, IEnumerable) 向一个文件中追加行,然后关闭该文件。如果指定文件不存在,此方法会创建一个文件,向其中写入指定的行,然后关闭该文件。
AppendAllText(String, String) 打开一个文件,向其中追加指定的字符串,然后关闭该文件。 如果文件不存在,此方法将创建一个文件,将指定的字符串写入文件,然后关闭该文件。
AppendText(String) 创建一个 StreamWriter,它将 UTF-8 编码文本追加到现有文件或新文件(如果指定文件不存在)。
Copy(String, String, Boolean) 将现有文件复制到新文件。 允许覆盖同名的文件。
Create(String) 在指定路径中创建或覆盖文件。
Delete(String) 删除指定的文件。
Exists(String) 确定指定的文件是否存在。
Move(String, String) 将指定文件移到新位置,提供要指定新文件名的选项。
Open(String, FileMode) 通过不共享的读/写访问权限打开指定路径上的 FileStream。
ReadAllText(String) 打开一个文本文件,读取文件中的所有文本,然后关闭此文件。

代码示例:

下面的示例展示了 File 类通过输入 Path 路径参数检查文件是否存在。如果不存在则先创建文件并写入文本内容,然后读取文本内容。如果存在则直接读取文本内容。在运行代码之前,请确保路径中 C 盘内有 test 文件。

using System;
using System.IO; 

public class Example
{
    static void FileIO(string path)
    {
        if (!File.Exists(path))
        {
            // 创建文件并写入
            using (StreamWriter sw = File.CreateText(path))     // using 关键字用于释放资源
            {
                sw.WriteLine("Hello");
                sw.WriteLine("World");
                sw.WriteLine("Hello, C#");
            }
        }

        // 打开要从中读取的文件。
        using (StreamReader sr = File.OpenText(path))
        {
            string? s;
            while ((s = sr.ReadLine()) != null)
            {
                Console.WriteLine(s);
            }
        }
    }

    static void Main(string[] args)
    {
        string path = @"c:\test\MyTest.txt";
        FileIO(path);
    }
}

点击了解更多 File 类的使用。

2.2 FileInfo 类

FileInfo 类提供用于创建、复制、删除、移动和打开文件的属性和实例方法,并且帮助创建 FileStream 对象。 此类不能被继承。File 类和 FileInfo 类两者的功能基本相同。但是 File 类是静态类,而 FileInfo 类是普通类类型,FileInfo 类需要实例化对象之后才可以调用其中的方法。

下表列出了 File 类中一些常用的方法:

方法名称 描述
AppendText() 创建一个 StreamWriter,它向 FileInfo 的此实例表示的文件追加文本。
CopyTo(String, Boolean) 将现有文件复制到新文件,允许覆盖现有文件。
Create() 创建文件。
CreateText() 创建写入新文本文件的 StreamWriter。
Delete() 永久删除文件。
Equals(Object) 确定指定对象是否等于当前对象。(继承自 Object)
GetType() 获取当前实例的 Type。(继承自 Object)
Open(FileMode) 在指定的模式中打开文件。
Refresh() 刷新对象的状态。(继承自 FileSystemInfo)
Replace(String, String) 使用当前 FileInfo 对象所描述的文件替换指定文件的内容,这一过程将删除原始文件,并创建被替换文件的备份。

代码示例:

FileInfo 类的示例和 File 类的示例差不多,但是 FileInfoIO 示例在 FileIO 示例的基础上增加了对 fi2 文件的删除和复制。

using System;
using System.IO;

public class Example
{
    static void FileInfoIO(string path, string path2)
    {
        var fi1 = new FileInfo(path);

        // 创建要写入的文件。   创建新的写入流 
        using (StreamWriter sw = fi1.CreateText())
        {
            sw.WriteLine("Hello");
            sw.WriteLine("And");
            sw.WriteLine("Welcome");
        }

        // 打开要读取的文件
        using (StreamReader sr = fi1.OpenText())
        {
            var s = "";
            while ((s = sr.ReadLine()) != null)
            {
                Console.WriteLine(s);
            }
        }

        try
        {
            var fi2 = new FileInfo(path2);

            //确保目标不存在。
            fi2.Delete();

            //复制文件。
            fi1.CopyTo(path2);
            Console.WriteLine($"{path} was copied to {path2}.");

            //删除新建的文件。
            fi2.Delete();
            Console.WriteLine($"{path2} was successfully deleted.");
        }
        catch (Exception e)
        {
            Console.WriteLine($"The process failed: {e.ToString()}");
        }
    }

    public static void Main()
    {
        string path = Path.GetTempFileName();
        string path2 = Path.GetTempFileName();

        FileInfoIO(path, path2);
    }
}

点击了解更多 FileInfo 类的使用。

2.3 FileStream 类

FileStream 类表示在磁盘或网络路径上指向文件的流。FileStream 使用类读取、写入、打开和关闭文件系统上的文件,操作其他与文件相关的操作系统句柄,包括管道、标准输入和标准输出。FileStream 类既支持同步读写操作,也支持异步读写操作。 File 类和 FileStream 类的关系就像是笔记本和笔的关系,笔记本的内容需要用笔来写。

下表列出了 FileStream 类中一些常用的方法:

方法名称 描述
Close() 关闭当前流并释放与之关联的所有资源(如套接字和文件句柄)。 不直接调用此方法,而应确保流得以正确释放。(继承自 Stream)
CopyTo(Stream) 从当前流中读取字节并将其写入到另一流中。 这两个流位置都以复制的字节数为高级。(继承自 Stream)
Dispose() 释放由 Stream 使用的所有资源。(继承自 Stream)
Finalize() 确保垃圾回收器回收 FileStream 时释放资源并执行其他清理操作。
Flush() 清除此流的缓冲区,使得所有缓冲数据都写入到文件中。
Read(Byte[], Int32, Int32) 从流中读取字节块并将该数据写入给定缓冲区中。
Seek(Int64, SeekOrigin) 将该流的当前位置设置为给定值。
Write(Byte[], Int32, Int32) 将字节块写入文件流。

代码示例:

下面的 FileStream 类示例和 File 类的示例逻辑差不多。不同的是程序中的文件流使用 FileStream 来实现,而且文件信息存储方式使用了封装的 AddText 方法实现。

using System;
using System.IO;
using System.Text;

public class Example
{
    private static void AddText(FileStream fs, string value)
    {
        byte[] info = new UTF8Encoding(true).GetBytes(value);
        fs.Write(info, 0, info.Length);
    }			
									
    static void FileStreamIO(string path)
    {
        // 如果文件存在,删除该文件。
        if (File.Exists(path))
        {
            File.Delete(path);
        }
				
        // 创建文件。
        using (FileStream fs = File.Create(path))
        {
            AddText(fs, "This is some text");
            AddText(fs, "This is some more text,");
            AddText(fs, "\r\nand this is on a new line");
            AddText(fs, "\r\n\r\nThe following is a subset of characters:\r\n");
			
            for (int i = 1; i < 120; i++)
            {
                AddText(fs, Convert.ToChar(i).ToString());
            }
        }

        // 打开流并读取它。
        using (FileStream fs = File.OpenRead(path))
        {
            byte[] b = new byte[1024];
            UTF8Encoding temp = new UTF8Encoding(true);

            int readLen;
            while ((readLen = fs.Read(b, 0, b.Length)) > 0)
            {
                Console.WriteLine(temp.GetString(b, 0, readLen));
            }
        }
    }

    public static void Main(string[] args)
    {
        string path = @"c:\test\MyTest.txt";
        FileStreamIO(path); 
    }
}

点击了解更多 FileStream 类的使用。

2.4 StreamReader 类

StreamReader 类也是用于读取文本文件的类, 在 C# 程序中 StreamReader 类继承自 TextReader 类。StreamReader 类以一种特定的编码从字节流中读取字符。

下表列出了 StreamReader 类中一些常用的方法:

方法名称 描述
Close() 关闭 StreamReader 对象和基础流,并释放与读取器关联的所有系统资源。
CreateObjRef(Type) 创建一个对象,该对象包含生成用于与远程对象进行通信的代理所需的全部相关信息。
Dispose() 释放由 TextReader 对象使用的所有资源。
Equals(Object) 确定指定对象是否等于当前对象。
Read() 读取输入流中的下一个字符并使该字符位置提升一个字符。
ReadLine() 从当前流中读取一行字符并将数据作为字符串返回。
ReadToEnd() 读取来自流的当前位置到结尾的所有字符。

代码示例:

下面的示例展示了 StreamReader 类的基本用法。 通过输入路径参数 path,StreamReader 类读取指定文件的内容信息并打印输出。如果文件不存在则直接输出无法读取文件的错误。

using System;
using System.IO;

public class Example
{
    public static void StreamReaderIO(string path)
    {
        try
        {
            //创建一个StreamReader实例从文件中读取
            // using语句同时关闭StreamReader。
            using (StreamReader sr = new StreamReader(path))
            {
                string line;

                //读取并显示文件中的行,直到
                //文件到达。
                while ((line = sr.ReadLine()) != null)
                {
                    Console.WriteLine(line);
                }
            }
        }
        catch (Exception e)
        {
            // 让用户知道哪里出错了。
            Console.WriteLine("The file could not be read:");
            Console.WriteLine(e.Message);
        }
    }

    public static void Main()
    {
        string path = "TestFile.txt";
        StreamReaderIO(path);
    }
}

点击了解更多 StreamReader 类的使用。

2.5 StreamWriter 类

StreamWriter 和 StreamReader 类类似。StreamReader 用于文本文件的读取,而 StreamWriter 用于文本文件的数据写入。其中 StreamWriter 类同样继承自 TextWriter 类。StreamWriter 类以一种特定的编码向流中写入字符。

下表列出了 StreamWriter 类中一些常用的方法:

方法名称 描述
Close() 关闭当前 StreamWriter 对象和基础流。
CreateObjRef(Type) 创建一个对象,该对象包含生成用于与远程对象进行通信的代理所需的全部相关信息。
Dispose() 释放由 TextWriter 对象使用的所有资源。
Equals(Object) 确定指定对象是否等于当前对象。
Flush() 清理当前写入器的所有缓冲区,并使所有缓冲数据写入基础流。
Write(String) 将字符串写入流。
WriteLine() 将行终止符写入文本流。

代码示例:

下面的示例展示了 StreamWriter 类的基本使用。使用 GetDirectories 方法获取 C 盘所有目录名称,再使用 StreamWriter 方法写入 CDriveDirs 文本文件。 再确保 sr 对象不为 null 的情况下打印输出 C 盘上所有目录名称。

using System;
using System.IO;

public class Example
{
    static void StreamWriterIO(string path)
    {
        // 获取当前C驱动器上的目录。
        DirectoryInfo[] cDirs = new DirectoryInfo(@"c:\").GetDirectories();

        // 将每个目录名写入一个文件。
        using (StreamWriter sw = new StreamWriter("CDriveDirs.txt"))
        {
            foreach (DirectoryInfo dir in cDirs)
            {
                sw.WriteLine(dir.Name);
            }
        }

        // 读取并显示文件中的每一行。
        string line = "";
        using (StreamReader sr = new StreamReader(path))
        {
            while ((line = sr.ReadLine()) != null)
            {
                Console.WriteLine(line);
            }
        }
    }

    static void Main(string[] args)
    {
        string path = "CDriveDirs.txt";
        StreamWriterIO(path);
    }
}

点击了解更多 StreamWriter 类的使用。

FileStream 和 StreamReader、StreamWriter 的区别:

  • FileStream 类在执行对文件的读写操作中,也包含了 StreamReader 和 StreamWriter 类的操作。
  • FileStream 类操作的是字节和字节数组,而 StreamReader 和 StreamWriter 类操作的是字符数据。
  • FileStream 适合对较大的文件进行操作, 而 StreamReader 和 StreamWriter 类适合对较小文件进行操作。

3,二进制文件操作

二进制文件和文本文件在广义上没有区别,但是在狭义上二进制文件与文本文件的区别在于以下几点:

  • 存储的数据类型不同。文本文件只能存储 char 类型字符变量,二进制文件可以存储 char、int 和 short 等很多类型的变量。
  • 读取的方式不同。文本文件只能被文本编辑器读取,比如记事本、记事板等,而二进制文件需要特殊的编码器,例如 png 等格式的图片文件需要用照片软件打开,mp4 等格式的视频需要用播放器打开。
  • 系统对文件的处理方式不同。例如 windows 系统对文本文件中的 ‘\n’ 换行符会进行隐式转换为 “\r\n”,而 Linux 系统则不会进行这样的操作。

在 C# 程序中,可以使用 BinaryReaderBinaryWriter 类对二进制文件进行读写操作。

3.1 BinaryReader 类

在 C# 中,BinaryReader 类用于从流中读取二进制信息。和 File 类一样,BinaryReader 类也位于 System.IO 命名空间中,而且 BinaryReader 类还支持以特定编码方式读取字符串。

下表列出了 BinaryReader 类中一些常用的方法:

方法名称 描述
Close() 关闭当前阅读器及基础流。
Dispose() 释放 BinaryReader 类的当前实例所使用的所有资源。
Read() 从基础流中读取字符,并根据所使用的 Encoding 和从流中读取的特定字符,提升流的当前位置。
ReadBoolean() 从当前流中读取 Boolean 值,并使该流的当前位置提升 1 个字节。
ReadByte() 从当前流中读取下一个字节,并使流的当前位置提升 1 个字节。
ReadChar() 从当前流中读取下一个字符,并根据所使用的 Encoding 和从流中读取的特定字符,提升流的当前位置。
ReadDecimal() 从当前流中读取十进制数值,并将该流的当前位置提升十六个字节。

方法示例:

下面的代码示例展示了 BinaryReader 类的基本使用。 在确保文件 AppSettings.dat 存在的情况下, 使用 BinaryReader 构造函数进行读取输出。实现了一个在文件中存储和检索应用程序设置的功能。

using System;
using System.IO;
using System.Text;

public class Example
{
    const string fileName = "AppSettings.dat";      // 文件名 
 
    // 写入默认的值 
    public static void WriteDefaultValues()
    {
        // 
        using (var stream = File.Open(fileName, FileMode.Create))
        {
            using (var writer = new BinaryWriter(stream, Encoding.UTF8, false))
            {
                writer.Write(1.250F);
                writer.Write(@"c:\Temp");
                writer.Write(10);
                writer.Write(true);
            }
        }
    }

    // 打印输出值 
    public static void DisplayValues()
    {
        float aspectRatio;
        string tempDirectory;
        int autoSaveTime;
        bool showStatusBar;

        if (File.Exists(fileName))
        {
            using (var stream = File.Open(fileName, FileMode.Open))
            {
                using (var reader = new BinaryReader(stream, Encoding.UTF8, false))
                {
                    aspectRatio = reader.ReadSingle();
                    tempDirectory = reader.ReadString();
                    autoSaveTime = reader.ReadInt32();
                    showStatusBar = reader.ReadBoolean();
                }
            }

            Console.WriteLine("Aspect ratio set to: " + aspectRatio);
            Console.WriteLine("Temp directory is: " + tempDirectory);
            Console.WriteLine("Auto save time set to: " + autoSaveTime);
            Console.WriteLine("Show status bar: " + showStatusBar);
        }
    }
    
    static void Main()
    {
        WriteDefaultValues();
        DisplayValues();
    } 
}

点击了解更多 BinaryReader 类的使用。

3.2 BinaryWriter 类

在 C# 程序中,BinaryWriter 和 BinaryReader 类分别用于从流中读取和写入二进制信息。BinaryWriter 和 BinaryReader 类类似。用于从流中写入二进制信息,而且支持用特定的编码写入字符串。

下表列出了 BinaryReader 类中一些常用的方法:

方法名称 描述
Close() 关闭当前的 BinaryWriter 和基础流。
Dispose() 释放 BinaryWriter 类的当前实例所使用的所有资源。
Seek(Int32, SeekOrigin) 设置当前流中的位置。
Write(Boolean) 将单字节 Boolean 值写入当前流,其中 0 表示 false,1 表示 true。
Write(Byte) 将一个无符号字节写入当前流,并将流的位置提升 1 个字节。
Write(Char) 将 Unicode 字符写入当前流,并根据所使用的 Encoding 和向流中写入的特定字符,提升流的当前位置。
Write(Decimal) 将一个十进制值写入当前流,并将流位置提升十六个字节。

代码示例:

在 BinaryReader 类的示例中已经用到了 BinaryWriter 类的功能。在程序当中创建打开了 AppSettings.dat 文件,并实例化了 BinaryWriter 类对象使用 Write 方法进行信息的写入。

// 写入默认的值 
public static void WriteDefaultValues()
{
    using (var stream = File.Open(fileName, FileMode.Create))
    {
        using (var writer = new BinaryWriter(stream, Encoding.UTF8, false))
        {
            writer.Write(1.250F);
            writer.Write(@"c:\Temp");
            writer.Write(10);
            writer.Write(true);
        }
    }
}

点击了解更多 BinaryWriter 类的使用。

4,文件目录操作

在 C# 中,允许使用 Directory、DirectoryInfo 等类进行对文件目录进行创建、枚举、移动等操作。

4.1 Directory 类

Directory 类 是一个公开用于通过目录和子目录进行创建、移动和枚举的静态方法。Directory 类位于 System.IO 命名空间,且 Directory 类不能被继承。

下表列出了 Directory 类中一些常用的方法:

方法名称 描述
CreateDirectory(String) 在指定路径中创建所有目录和子目录,除非它们已经存在。
Delete(String) 从指定路径删除空目录。
EnumerateDirectories(String) 返回指定路径中的目录完整名称的可枚举集合。
Exists(String) 确定给定路径是否引用磁盘上的现有目录。
GetCreationTime(String) 获取目录的创建日期和时间。
GetFiles(String) 返回指定目录中文件的名称(包括其路径)。
GetFileSystemEntries(String) 返回指定路径中的所有文件和子目录的名称。
Move(String, String) 将文件或目录及其内容移到新位置。
ResolveLinkTarget(String, Boolean) 获取指定目录链接的目标。
SetCreationTime(String, DateTime) 为指定的文件或目录设置创建日期和时间。

代码示例:

以下的示例展示了 Directoy 类如何从目录中检索所有文本文件并将其移动到新目录。移动文件后,它们不再存在于原始目录中。在运行之前请确保 C 盘内有 current 和 archive 文件。

using System;
using System.IO;

public class Example
{
    static void DirectoryIO(string sourceDirectory, string archiveDirectory)
    {
        try
        {
            var txtFiles = Directory.EnumerateFiles(sourceDirectory, "*.txt");

            foreach (string currentFile in txtFiles)
            {
                string fileName = currentFile.Substring(sourceDirectory.Length + 1);
                Directory.Move(currentFile, Path.Combine(archiveDirectory, fileName));
                Console.WriteLine("current文件中的txt文本文件移动到了archive文件中");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    static void Main(string[] args)
    {
        string sourceDirectory = @"C:\current";
        string archiveDirectory = @"C:\archive";
        DirectoryIO(sourceDirectory, archiveDirectory);
    }
}

点击了解更多 Directory 类的使用。

4.2 DirectoryInfo类

DirectoryInfo 类和 Directory 类两者的功能基本相同,只不过 DirectoryInfo 类是一个实例方法,而Directory 类是一个静态方法。DirectoryInfo 类位于 System.IO 命名空间,且 DirectoryInfo 类不能被继承。

下表列出了 DirectoryInfo 类中一些常用的方法:

方法名称 描述
Create() 创建目录。
CreateObjRef(Type) 创建一个对象,该对象包含生成用于与远程对象进行通信的代理所需的全部相关信息。
Delete() 如果此 DirectoryInfo 为空则将其删除。
EnumerateDirectories() 返回当前目录中的目录信息的可枚举集合。
GetDirectories() 返回当前目录的子目录。
GetFiles() 返回当前目录的文件列表。
MoveTo(String) 将 DirectoryInfo 实例及其内容移动到新路径。
Refresh() 刷新对象的状态。

代码示例:

using System;
using System.IO;

public class Example
{
    static void DirectoryInfoIO(string path)
    {
        // 指定要操作的目录。
        DirectoryInfo di = new DirectoryInfo(path);
        try
        {
            // 确定目录是否存在。
            if (di.Exists)
            {
                //表示目录已经存在。
                Console.WriteLine("这条路径已经存在了。");
                return;
            }

            // 尝试创建目录。
            di.Create();
            Console.WriteLine("创建目录成功。");

            // 删除目录。
            di.Delete();
            Console.WriteLine("删除目录成功。");
        }
        catch (Exception e)
        {
            Console.WriteLine("进程失败: {0}", e.ToString());
        }
    }

    public static void Main()
    {
        string path = @"c:\MyDir";
        DirectoryInfoIO(path);
    }
}

点击了解更多 DirectoryInfo 类的使用。


结语

☁️ 以上就是 C# 文件与IO的介绍啦,希望能够对大家有所帮助。望大家多多支持,你们的支持就是笔者创作最大的动力!

你可能感兴趣的:(从基础到进阶系列,c#,开发语言,.net,微软)