【C#编程指南】 文件系统和注册表编程指南与实战

简介: 本文主要介绍了如何使用 C# 和 .NET 对文件和文件夹执行各种基本操作。
🐋作者简介:博主是一位.Net开发者,同时也是RPA和低代码平台的践行者。
🐬个人主页: 会敲键盘的肘子
🐰系列专栏: .Net实用方法总结
🦀专栏简介:博主针对.Net开发和C站问答过程中遇到的问题进行总结,形成本专栏,希望可以帮助到您解决问题。
🐶座右铭:总有一天你所坚持的会反过来拥抱你。

🌈写在前面:

本文主要介绍了如何使用 C# 和 .NET 对文件和文件夹执行各种基本操作。


👉本文关键字:System.IO、文件系统、方法示例、C#编程指南

[TOC]

1️⃣ System.IO命名空间

.NET中的IO操作命名空间,包含允许读写文件数据流的类型以及提供基本文件和目录支持的类型。

我们在.NET中的IO操作,经常需要调用一下几个类。

  • FileStream类

​ 文件流类,负责大文件的拷贝,读写。

  • Path类

​ Path类中方法,基本都是对字符串(文件名)的操作,与实际文件没多大关系。

  • File类

    File类可以进行一些对小文件拷贝、剪切操作,还能读一些文档文件。

  • Dirctory类

    目录操作,创建文件、删除目录,获取目录下文件名等等。

2️⃣ 如何循环访问目录树

♈ 场景需求

访问特定根文件夹下的每个嵌套子目录中的每个文件,可以是任意深度。 不需要打开每个文件。 可以以 string 的形式只检索文件或子目录的名称,也可以以 System.IO.FileInfoSystem.IO.DirectoryInfo 对象的形式检索其他信息。

♊ 解决方案

⭐ 前序遍历

遍历目录树时,可以先处理文件(前序遍历)。执行前序遍历,则可直接访问该文件夹本身下的文件,然后遍历当前文件夹下的整个树。 本文档后面的示例执行的是前序遍历,但你可以轻松地修改它们以执行后序遍历。

⭐ 后序遍历

遍历目录树时,先处理子目录(后序遍历)。 后序遍历在访问当前文件夹的文件之前遍历下面的整个树。 本文档后面的示例执行的是前序遍历,但你可以轻松地修改它们以执行后序遍历。

⭐ 递归遍历

下面的示例演示如何以递归方式遍历目录树。 递归方法是一种很好的方法,但是如果目录树较大且嵌套深度较深,则可能引起堆栈溢出异常。

在每个文件或文件夹上处理的特定异常和执行的特定操作仅作为示例提供。 你可以修改此代码来满足你的特定要求。 有关详细信息,请参阅代码中的注释。

示例

public class RecursiveFileSearch
{
    static System.Collections.Specialized.StringCollection log = new System.Collections.Specialized.StringCollection();

    static void Main()
    {
        // Start with drives if you have to search the entire computer.
        string[] drives = System.Environment.GetLogicalDrives();

        foreach (string dr in drives)
        {
            System.IO.DriveInfo di = new System.IO.DriveInfo(dr);

            // Here we skip the drive if it is not ready to be read. This
            // is not necessarily the appropriate action in all scenarios.
            if (!di.IsReady)
            {
                Console.WriteLine("The drive {0} could not be read", di.Name);
                continue;
            }
            System.IO.DirectoryInfo rootDir = di.RootDirectory;
            WalkDirectoryTree(rootDir);
        }

        // Write out all the files that could not be processed.
        Console.WriteLine("Files with restricted access:");
        foreach (string s in log)
        {
            Console.WriteLine(s);
        }
        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key");
        Console.ReadKey();
    }

    static void WalkDirectoryTree(System.IO.DirectoryInfo root)
    {
        System.IO.FileInfo[] files = null;
        System.IO.DirectoryInfo[] subDirs = null;

        // First, process all the files directly under this folder
        try
        {
            files = root.GetFiles("*.*");
        }
        // This is thrown if even one of the files requires permissions greater
        // than the application provides.
        catch (UnauthorizedAccessException e)
        {
            // This code just writes out the message and continues to recurse.
            // You may decide to do something different here. For example, you
            // can try to elevate your privileges and access the file again.
            log.Add(e.Message);
        }

        catch (System.IO.DirectoryNotFoundException e)
        {
            Console.WriteLine(e.Message);
        }

        if (files != null)
        {
            foreach (System.IO.FileInfo fi in files)
            {
                // In this example, we only access the existing FileInfo object. If we
                // want to open, delete or modify the file, then
                // a try-catch block is required here to handle the case
                // where the file has been deleted since the call to TraverseTree().
                Console.WriteLine(fi.FullName);
            }

            // Now find all the subdirectories under this directory.
            subDirs = root.GetDirectories();

            foreach (System.IO.DirectoryInfo dirInfo in subDirs)
            {
                // Resursive call for each subdirectory.
                WalkDirectoryTree(dirInfo);
            }
        }
    }
}
⭐ 基于堆栈的遍历

下面的示例演示如何不使用递归方式遍历目录树中的文件和文件夹。 此方法使用泛型 Stack 集合类型,此集合类型是一个后进先出 (LIFO) 堆栈

在每个文件或文件夹上处理的特定异常和执行的特定操作仅作为示例提供。 你可以修改此代码来满足你的特定要求。 有关详细信息,请参阅代码中的注释。

示例

public class StackBasedIteration
{
    static void Main(string[] args)
    {
        // Specify the starting folder on the command line, or in
        // Visual Studio in the Project > Properties > Debug pane.
        TraverseTree(args[0]);

        Console.WriteLine("Press any key");
        Console.ReadKey();
    }

    public static void TraverseTree(string root)
    {
        // Data structure to hold names of subfolders to be
        // examined for files.
        Stack<string> dirs = new Stack<string>(20);

        if (!System.IO.Directory.Exists(root))
        {
            throw new ArgumentException();
        }
        dirs.Push(root);

        while (dirs.Count > 0)
        {
            string currentDir = dirs.Pop();
            string[] subDirs;
            try
            {
                subDirs = System.IO.Directory.GetDirectories(currentDir);
            }
            // An UnauthorizedAccessException exception will be thrown if we do not have
            // discovery permission on a folder or file. It may or may not be acceptable
            // to ignore the exception and continue enumerating the remaining files and
            // folders. It is also possible (but unlikely) that a DirectoryNotFound exception
            // will be raised. This will happen if currentDir has been deleted by
            // another application or thread after our call to Directory.Exists. The
            // choice of which exceptions to catch depends entirely on the specific task
            // you are intending to perform and also on how much you know with certainty
            // about the systems on which this code will run.
            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine(e.Message);
                continue;
            }
            catch (System.IO.DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
                continue;
            }

            string[] files = null;
            try
            {
                files = System.IO.Directory.GetFiles(currentDir);
            }

            catch (UnauthorizedAccessException e)
            {

                Console.WriteLine(e.Message);
                continue;
            }

            catch (System.IO.DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
                continue;
            }
            // Perform the required action on each file here.
            // Modify this block to perform your required task.
            foreach (string file in files)
            {
                try
                {
                    // Perform whatever action is required in your scenario.
                    System.IO.FileInfo fi = new System.IO.FileInfo(file);
                    Console.WriteLine("{0}: {1}, {2}", fi.Name, fi.Length, fi.CreationTime);
                }
                catch (System.IO.FileNotFoundException e)
                {
                    // If file was deleted by a separate application
                    //  or thread since the call to TraverseTree()
                    // then just continue.
                    Console.WriteLine(e.Message);
                    continue;
                }
            }

            // Push the subdirectories onto the stack for traversal.
            // This could also be done before handing the files.
            foreach (string str in subDirs)
                dirs.Push(str);
        }
    }
}
如果需要对文件和文件夹执行各种操作,则可以 模块化这些示例,方法是将操作 重构可使用单个委托进行调用的单独的函数

通常,检测每个文件夹以确定应用程序是否有权限打开它是一个很费时的过程。 因此,此代码示例只将此部分操作封装在 try/catch 块中。 你可以修改 catch 块,以便在拒绝访问某个文件夹时,可以尝试提升权限,然后再次访问此文件夹。 一般来说,仅捕获可以处理的、不会将应用程序置于未知状态的异常。

如果必须在内存或磁盘上存储目录树的内容,那么最佳选择是仅存储每个文件的 FullName 属性(类型为 string)。 然后可以根据需要使用此字符串创建新的 FileInfoDirectoryInfo 对象,或打开需要进行其他处理的任何文件。

3️⃣ 如何获取有关文件、文件夹和驱动器的信息

♈ 场景需求

获取有关文件、文件夹和驱动器的信息。

♊ 解决方案

在 .NET 中,可以使用以下类访问文件系统信息:

FileInfoDirectoryInfo 类表示文件或目录,并包含用于公开 NTFS 文件系统所支持的许多文件特性的属性。 它们还包含用于打开、关闭、移动和删除文件和文件夹的方法。 可以通过将表示文件、文件夹或驱动器名称的字符串传入构造函数来创建这些类的实例:

System.IO.DriveInfo di = new System.IO.DriveInfo(@"C:\");  

还可以使用对 DirectoryInfo.GetDirectoriesDirectoryInfo.GetFilesDriveInfo.RootDirectory 的调用来获取文件、文件夹或驱动器的名称。

System.IO.DirectorySystem.IO.File 类提供相关静态方法,用于检索有关目录和文件的信息。

示例

class FileSysInfo
{
    static void Main()
    {
        // You can also use System.Environment.GetLogicalDrives to
        // obtain names of all logical drives on the computer.
        System.IO.DriveInfo di = new System.IO.DriveInfo(@"C:\");
        Console.WriteLine(di.TotalFreeSpace);
        Console.WriteLine(di.VolumeLabel);

        // Get the root directory and print out some information about it.
        System.IO.DirectoryInfo dirInfo = di.RootDirectory;
        Console.WriteLine(dirInfo.Attributes.ToString());

        // Get the files in the directory and print out some information about them.
        System.IO.FileInfo[] fileNames = dirInfo.GetFiles("*.*");

        foreach (System.IO.FileInfo fi in fileNames)
        {
            Console.WriteLine("{0}: {1}: {2}", fi.Name, fi.LastAccessTime, fi.Length);
        }

        // Get the subdirectories directly that is under the root.
        // See "How to: Iterate Through a Directory Tree" for an example of how to
        // iterate through an entire tree.
        System.IO.DirectoryInfo[] dirInfos = dirInfo.GetDirectories("*.*");

        foreach (System.IO.DirectoryInfo d in dirInfos)
        {
            Console.WriteLine(d.Name);
        }

        // The Directory and File classes provide several static methods
        // for accessing files and directories.

        // Get the current application directory.
        string currentDirName = System.IO.Directory.GetCurrentDirectory();
        Console.WriteLine(currentDirName);

        // Get an array of file names as strings rather than FileInfo objects.
        // Use this method when storage space is an issue, and when you might
        // hold on to the file name reference for a while before you try to access
        // the file.
        string[] files = System.IO.Directory.GetFiles(currentDirName, "*.txt");

        foreach (string s in files)
        {
            // Create the FileInfo object only when needed to ensure
            // the information is as current as possible.
            System.IO.FileInfo fi = null;
            try
            {
                 fi = new System.IO.FileInfo(s);
            }
            catch (System.IO.FileNotFoundException e)
            {
                // To inform the user and continue is
                // sufficient for this demonstration.
                // Your application may require different behavior.
                Console.WriteLine(e.Message);
                continue;
            }
            Console.WriteLine("{0} : {1}",fi.Name, fi.Directory);
        }

        // Change the directory. In this case, first check to see
        // whether it already exists, and create it if it does not.
        // If this is not appropriate for your application, you can
        // handle the System.IO.IOException that will be raised if the
        // directory cannot be found.
        if (!System.IO.Directory.Exists(@"C:\Users\Public\TestFolder\"))
        {
            System.IO.Directory.CreateDirectory(@"C:\Users\Public\TestFolder\");
        }

        System.IO.Directory.SetCurrentDirectory(@"C:\Users\Public\TestFolder\");

        currentDirName = System.IO.Directory.GetCurrentDirectory();
        Console.WriteLine(currentDirName);

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}

♎ 最佳实践

处理用户指定的路径字符串时,还应针对以下情况处理异常

  • 文件名格式不正确。 例如,它包含无效字符或只包含空格。
  • 文件名为 null。
  • 文件名超过系统定义的最大长度。
  • 文件名包含冒号 (:)。

如果应用程序没有足够权限来读取指定文件,Exists 方法会返回 false(无论路径是否存在);该方法不会引发异常。

4️⃣ 如何创建文件或文件夹

♈ 场景需求

可通过编程方式在计算机上创建文件夹、子文件夹和子文件夹中的文件,并将数据写入文件。

♊ 解决方案

示例

public class CreateFileOrFolder
{
    static void Main()
    {
        // Specify a name for your top-level folder.
        string folderName = @"c:\Top-Level Folder";

        // To create a string that specifies the path to a subfolder under your
        // top-level folder, add a name for the subfolder to folderName.
        string pathString = System.IO.Path.Combine(folderName, "SubFolder");

        // You can write out the path name directly instead of using the Combine
        // method. Combine just makes the process easier.
        string pathString2 = @"c:\Top-Level Folder\SubFolder2";

        // You can extend the depth of your path if you want to.
        //pathString = System.IO.Path.Combine(pathString, "SubSubFolder");

        // Create the subfolder. You can verify in File Explorer that you have this
        // structure in the C: drive.
        //    Local Disk (C:)
        //        Top-Level Folder
        //            SubFolder
        System.IO.Directory.CreateDirectory(pathString);

        // Create a file name for the file you want to create.
        string fileName = System.IO.Path.GetRandomFileName();

        // This example uses a random string for the name, but you also can specify
        // a particular name.
        //string fileName = "MyNewFile.txt";

        // Use Combine again to add the file name to the path.
        pathString = System.IO.Path.Combine(pathString, fileName);

        // Verify the path that you have constructed.
        Console.WriteLine("Path to my file: {0}\n", pathString);

        // Check that the file doesn't already exist. If it doesn't exist, create
        // the file and write integers 0 - 99 to it.
        // DANGER: System.IO.File.Create will overwrite the file if it already exists.
        // This could happen even with random file names, although it is unlikely.
        if (!System.IO.File.Exists(pathString))
        {
            using (System.IO.FileStream fs = System.IO.File.Create(pathString))
            {
                for (byte i = 0; i < 100; i++)
                {
                    fs.WriteByte(i);
                }
            }
        }
        else
        {
            Console.WriteLine("File \"{0}\" already exists.", fileName);
            return;
        }

        // Read and display the data from your file.
        try
        {
            byte[] readBuffer = System.IO.File.ReadAllBytes(pathString);
            foreach (byte b in readBuffer)
            {
                Console.Write(b + " ");
            }
            Console.WriteLine();
        }
        catch (System.IO.IOException e)
        {
            Console.WriteLine(e.Message);
        }

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
    // Sample output:

    // Path to my file: c:\Top-Level Folder\SubFolder\ttxvauxe.vv0

    //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
    //30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
    // 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 8
    //3 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
}

如果文件夹已存在,CreateDirectory 不执行任何操作,未引发任何异常。 但 File.Create 用新文件替换现有文件。 本示例使用 if-else 语句阻止替换现有文件。

通过在示例中作出以下更改,可根据具有特定名称的文件是否存在来指定不同的结果。 如果该文件不存在,代码就会创建一个文件。 如果该文件存在,代码就会将数据追加到该文件中。

  • 指定一个非随机文件名。

    // Comment out the following line.  
    //string fileName = System.IO.Path.GetRandomFileName();  
    
    // Replace that line with the following assignment.  
    string fileName = "MyNewFile.txt";  
  • 用以下代码中的 using 语句替换 if-else 语句。

    using (System.IO.FileStream fs = new System.IO.FileStream(pathString, FileMode.Append))
    {  
        for (byte i = 0; i < 100; i++)  
        {  
            fs.WriteByte(i);  
        }  
    }  

多次运行此示例,验证数据是否每次都添加到了文件中。

有关可尝试的 FileMode 值,请参阅 FileMode

♎ 最佳实践

以下情况可能会导致异常

5️⃣ 如何复制、删除和移动文件和文件夹

♈ 场景需求

复制文件和目录。

♊ 解决方案

以下示例演示如何从 System.IO 命名空间使用 System.IO.FileSystem.IO.DirectorySystem.IO.FileInfoSystem.IO.DirectoryInfo 类以同步方式复制、移动和删除文件与文件夹。 这些示例未提供进度栏或其他任何用户界面。

操作多个文件时,请使用 System.IO.FileSystemWatcher 提供事件,以便可以计算进度。

示例

以下示例演示如何复制文件和目录。

// Simple synchronous file copy operations with no user interface.
// To run this sample, first create the following directories and files:
// C:\Users\Public\TestFolder
// C:\Users\Public\TestFolder\test.txt
// C:\Users\Public\TestFolder\SubDir\test.txt
public class SimpleFileCopy
{
    static void Main()
    {
        string fileName = "test.txt";
        string sourcePath = @"C:\Users\Public\TestFolder";
        string targetPath =  @"C:\Users\Public\TestFolder\SubDir";

        // Use Path class to manipulate file and directory paths.
        string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
        string destFile = System.IO.Path.Combine(targetPath, fileName);

        // To copy a folder's contents to a new location:
        // Create a new target folder.
        // If the directory already exists, this method does not create a new directory.
        System.IO.Directory.CreateDirectory(targetPath);

        // To copy a file to another location and
        // overwrite the destination file if it already exists.
        System.IO.File.Copy(sourceFile, destFile, true);

        // To copy all the files in one directory to another directory.
        // Get the files in the source folder. (To recursively iterate through
        // all subfolders under the current directory, see
        // "How to: Iterate Through a Directory Tree.")
        // Note: Check for target path was performed previously
        //       in this code example.
        if (System.IO.Directory.Exists(sourcePath))
        {
            string[] files = System.IO.Directory.GetFiles(sourcePath);

            // Copy the files and overwrite destination files if they already exist.
            foreach (string s in files)
            {
                // Use static Path methods to extract only the file name from the path.
                fileName = System.IO.Path.GetFileName(s);
                destFile = System.IO.Path.Combine(targetPath, fileName);
                System.IO.File.Copy(s, destFile, true);
            }
        }
        else
        {
            Console.WriteLine("Source path does not exist!");
        }

        // Keep console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}

以下示例演示如何移动文件和目录。

// Simple synchronous file move operations with no user interface.
public class SimpleFileMove
{
    static void Main()
    {
        string sourceFile = @"C:\Users\Public\public\test.txt";
        string destinationFile = @"C:\Users\Public\private\test.txt";

        // To move a file or folder to a new location:
        System.IO.File.Move(sourceFile, destinationFile);

        // To move an entire directory. To programmatically modify or combine
        // path strings, use the System.IO.Path class.
        System.IO.Directory.Move(@"C:\Users\Public\public\test\", @"C:\Users\Public\private");
    }
}

以下示例演示如何删除文件和目录。

// Simple synchronous file deletion operations with no user interface.
// To run this sample, create the following files on your drive:
// C:\Users\Public\DeleteTest\test1.txt
// C:\Users\Public\DeleteTest\test2.txt
// C:\Users\Public\DeleteTest\SubDir\test2.txt

public class SimpleFileDelete
{
    static void Main()
    {
        // Delete a file by using File class static method...
        if(System.IO.File.Exists(@"C:\Users\Public\DeleteTest\test.txt"))
        {
            // Use a try block to catch IOExceptions, to
            // handle the case of the file already being
            // opened by another process.
            try
            {
                System.IO.File.Delete(@"C:\Users\Public\DeleteTest\test.txt");
            }
            catch (System.IO.IOException e)
            {
                Console.WriteLine(e.Message);
                return;
            }
        }

        // ...or by using FileInfo instance method.
        System.IO.FileInfo fi = new System.IO.FileInfo(@"C:\Users\Public\DeleteTest\test2.txt");
        try
        {
            fi.Delete();
        }
        catch (System.IO.IOException e)
        {
            Console.WriteLine(e.Message);
        }

        // Delete a directory. Must be writable or empty.
        try
        {
            System.IO.Directory.Delete(@"C:\Users\Public\DeleteTest");
        }
        catch (System.IO.IOException e)
        {
            Console.WriteLine(e.Message);
        }
        // Delete a directory and all subdirectories with Directory static method...
        if(System.IO.Directory.Exists(@"C:\Users\Public\DeleteTest"))
        {
            try
            {
                System.IO.Directory.Delete(@"C:\Users\Public\DeleteTest", true);
            }

            catch (System.IO.IOException e)
            {
                Console.WriteLine(e.Message);
            }
        }

        // ...or with DirectoryInfo instance method.
        System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(@"C:\Users\Public\public");
        // Delete this dir and all subdirs.
        try
        {
            di.Delete(true);
        }
        catch (System.IO.IOException e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

6️⃣ 如何提供文件操作进度对话框

♈ 场景需求

Microsoft.VisualBasic 命名空间中使用 CopyFile(String, String, UIOption)) 方法,可以在 Windows 中提供显示文件操作进度的标准对话框。

♊ 解决方案

在 Visual Studio 中添加引用

  1. 在菜单栏上,依次选择“项目”、“添加引用”。

    此时将显示“引用管理器”对话框。

  2. 在“程序集”区域,选择“Framework”(如果尚未选择它)。
  3. 在名称列表中,选择“Microsoft.VisualBasic”复选框,然后再选择“确定”按钮以关闭对话框。

示例

以下代码将 sourcePath 指定的目录复制到 destinationPath 指定的目录。 此代码还提供了标准的对话框,其中显示在操作完成前估计的剩余时间量。

// The following using directive requires a project reference to Microsoft.VisualBasic.
using Microsoft.VisualBasic.FileIO;

class FileProgress
{
    static void Main()
    {
        // Specify the path to a folder that you want to copy. If the folder is small,
        // you won't have time to see the progress dialog box.
        string sourcePath = @"C:\Windows\symbols\";
        // Choose a destination for the copied files.
        string destinationPath = @"C:\TestFolder";

        FileSystem.CopyDirectory(sourcePath, destinationPath,
            UIOption.AllDialogs);
    }
}

7️⃣ 如何写入文本文件

♈ 场景需求

本文提供了几个示例,演示了将文本写入文件的多种方法。

♊ 解决方案

前两个示例使用 System.IO.File 类上的静态便捷方法将任意 IEnumerable<string> 的每个元素和 string 写入文本文件。 第三个示例演示了在写入文件时必须分别处理文本的每一行的情况下,如何将文本添加到文件。 在前三个示例中,会覆盖文件中的所有现有内容。 最后一个示例演示如何将文本追加到现有文件。

这些示例都将字符串文本写入了文件。 如果想设置写入文件的文本的格式,请使用 Format 方法或 C# 字符串内插功能。

⭐ 将字符串的集合写入文件
class WriteAllLines
{
    public static async Task ExampleAsync()
    {
        string[] lines =
        {
            "First line", "Second line", "Third line" 
        };

        await File.WriteAllLinesAsync("WriteLines.txt", lines);
    }
}

前面的源代码示例:

  • 使用三个值实例化字符串数组。
  • 等待对 File.WriteAllLinesAsync 的调用完成,该调用会执行以下操作:

    • 以异步方式创建一个名为“WriteLines.txt”的文件。 如果该文件已存在,则会覆盖该文件。
    • 将给定行写入该文件。
    • 关闭该文件,并根据需要自动刷新和释放。
⭐ 向文件写入一个字符串
class WriteAllText
{
    public static async Task ExampleAsync()
    {
        string text =
            "A class is the most powerful data type in C#. Like a structure, " +
            "a class defines the data and behavior of the data type. ";

        await File.WriteAllTextAsync("WriteText.txt", text);
    }
}

前面的源代码示例:

  • 根据指定的字符串字面量实例化一个字符串。
  • 等待对 File.WriteAllTextAsync 的调用完成,该调用会执行以下操作:

    • 以异步方式创建一个名为“WriteText.txt”的文件。 如果该文件已存在,则会覆盖该文件。
    • 将给定文本写入该文件。
    • 关闭该文件,并根据需要自动刷新和释放。
⭐ 将数组中的选定字符串写入文件
class StreamWriterOne
{
    public static async Task ExampleAsync()
    {
        string[] lines = { "First line", "Second line", "Third line" };
        using StreamWriter file = new("WriteLines2.txt");

        foreach (string line in lines)
        {
            if (!line.Contains("Second"))
            {
                await file.WriteLineAsync(line);
            }
        }
    }
}

前面的源代码示例:

  • 使用三个值实例化字符串数组。
  • using 声明的形式使用 WriteLines2.txt 的文件路径实例化 StreamWriter
  • 循环访问所有行。
  • 有条件地等待对 StreamWriter.WriteLineAsync(String)) 的调用完成,该调用在行不包含 "Second" 时将该行写入文件。
⭐ 将文本追加到现有文件
class StreamWriterTwo
{
    public static async Task ExampleAsync()
    {
        using StreamWriter file = new("WriteLines2.txt", append: true);
        await file.WriteLineAsync("Fourth line");
    }
}

前面的源代码示例:

♎ 最佳实践

以下情况可能会导致异常

使用文件系统时,还有其他可能会导致异常的情况,因此最好进行防御性编程。

8️⃣ 如何读取文本文件中的内容

♈ 场景需求

通过使用 System.IO.File 类的 ReadAllTextReadAllLines 静态方法来确定文本文件的内容。

♊ 解决方案

示例

class ReadFromFile
{
    static void Main()
    {
        // The files used in this example are created in the topic
        // How to: Write to a Text File. You can change the path and
        // file name to substitute text files of your own.

        // Example #1
        // Read the file as one string.
        string text = System.IO.File.ReadAllText(@"C:\Users\Public\TestFolder\WriteText.txt");

        // Display the file contents to the console. Variable text is a string.
        System.Console.WriteLine("Contents of WriteText.txt = {0}", text);

        // Example #2
        // Read each line of the file into a string array. Each element
        // of the array is one line of the file.
        string[] lines = System.IO.File.ReadAllLines(@"C:\Users\Public\TestFolder\WriteLines2.txt");

        // Display the file contents by using a foreach loop.
        System.Console.WriteLine("Contents of WriteLines2.txt = ");
        foreach (string line in lines)
        {
            // Use a tab to indent each line of the file.
            Console.WriteLine("\t" + line);
        }

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}

♎ 最佳实践

以下情况可能会导致异常

  • 不存在该文件,或者指定位置不存在该文件。 检查文件名的路径和拼写。

9️⃣ 如何一次一行地读取文本文件

♈ 场景需求

使用 File 类的 ReadLines 方法,一次一行地将文本文件内容读入字符串。 每个文本行都存储到字符串 line 中并显示在屏幕上。

♊ 解决方案

示例

int counter = 0;  
  
// Read the file and display it line by line.  
foreach (string line in System.IO.File.ReadLines(@"c:\test.txt"))
{  
    System.Console.WriteLine(line);  
    counter++;  
}  
  
System.Console.WriteLine("There were {0} lines.", counter);  
// Suspend the screen.  
System.Console.ReadLine();

♎ 最佳实践

以下情况可能会导致异常

  • 文件可能不存在。

⭐写在结尾:

文章中出现的任何错误请大家批评指出,一定及时修改。

希望写在这里的小伙伴能给个三连支持

相关文章
|
1月前
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
35 3
|
2天前
|
存储 安全 编译器
学懂C#编程:属性(Property)的概念定义及使用详解
通过深入理解和使用C#的属性,可以编写更清晰、简洁和高效的代码,为开发高质量的应用程序奠定基础。
31 12
|
1月前
|
设计模式 C# 图形学
Unity 游戏引擎 C# 编程:一分钟浅谈
本文介绍了在 Unity 游戏开发中使用 C# 的基础知识和常见问题。从 `MonoBehavior` 类的基础用法,到变量和属性的管理,再到空引用异常、资源管理和性能优化等常见问题的解决方法。文章还探讨了单例模式、事件系统和数据持久化等高级话题,旨在帮助开发者避免常见错误,提升游戏开发效率。
51 4
|
2月前
|
开发框架 NoSQL MongoDB
C#/.NET/.NET Core开发实战教程集合
C#/.NET/.NET Core开发实战教程集合
|
3月前
|
API C#
C# 一分钟浅谈:文件系统编程
在软件开发中,文件系统操作至关重要。本文将带你快速掌握C#中文件系统编程的基础知识,涵盖基本概念、常见问题及解决方法。文章详细介绍了`System.IO`命名空间下的关键类库,并通过示例代码展示了路径处理、异常处理、并发访问等技巧,还提供了异步API和流压缩等高级技巧,帮助你写出更健壮的代码。
51 2
|
2月前
|
安全 C# 数据安全/隐私保护
实现C#编程文件夹加锁保护
【10月更文挑战第16天】本文介绍了两种用 C# 实现文件夹保护的方法:一是通过设置文件系统权限,阻止普通用户访问;二是使用加密技术,对文件夹中的文件进行加密,防止未授权访问。提供了示例代码和使用方法,适用于不同安全需求的场景。
142 0
|
3月前
|
SQL 开发框架 安全
并发集合与任务并行库:C#中的高效编程实践
在现代软件开发中,多核处理器普及使多线程编程成为提升性能的关键。然而,传统同步模型在高并发下易引发死锁等问题。为此,.NET Framework引入了任务并行库(TPL)和并发集合,简化并发编程并增强代码可维护性。并发集合允许多线程安全访问,如`ConcurrentQueue&lt;T&gt;`和`ConcurrentDictionary&lt;TKey, TValue&gt;`,有效避免数据不一致。TPL则通过`Task`类实现异步操作,提高开发效率。正确使用这些工具可显著提升程序性能,但也需注意任务取消和异常处理等常见问题。
56 1
|
7月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
216 3
|
7月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
207 3
|
3月前
|
安全 程序员 编译器
C#一分钟浅谈:泛型编程基础
在现代软件开发中,泛型编程是一项关键技能,它使开发者能够编写类型安全且可重用的代码。C# 自 2.0 版本起支持泛型编程,本文将从基础概念入手,逐步深入探讨 C# 中的泛型,并通过具体实例帮助理解常见问题及其解决方法。泛型通过类型参数替代具体类型,提高了代码复用性和类型安全性,减少了运行时性能开销。文章详细介绍了如何定义泛型类和方法,并讨论了常见的易错点及解决方案,帮助读者更好地掌握这一技术。
84 11