🐋作者简介:博主是一位.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.FileInfo 或 System.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
)。 然后可以根据需要使用此字符串创建新的 FileInfo 或 DirectoryInfo 对象,或打开需要进行其他处理的任何文件。
3️⃣ 如何获取有关文件、文件夹和驱动器的信息
♈ 场景需求
获取有关文件、文件夹和驱动器的信息。
♊ 解决方案
在 .NET 中,可以使用以下类访问文件系统信息:
FileInfo 和 DirectoryInfo 类表示文件或目录,并包含用于公开 NTFS 文件系统所支持的许多文件特性的属性。 它们还包含用于打开、关闭、移动和删除文件和文件夹的方法。 可以通过将表示文件、文件夹或驱动器名称的字符串传入构造函数来创建这些类的实例:
System.IO.DriveInfo di = new System.IO.DriveInfo(@"C:\");
还可以使用对 DirectoryInfo.GetDirectoriesDirectoryInfo.GetFiles 和 DriveInfo.RootDirectory 的调用来获取文件、文件夹或驱动器的名称。
System.IO.Directory 和 System.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。
♎ 最佳实践
以下情况可能会导致异常:
- 文件夹名称格式不正确。 例如,它包含非法字符或它仅为空格(ArgumentException 类)。 使用 Path 类创建有效的路径名。
- 要创建的文件夹的父文件夹为只读(IOException 类)。
- 文件夹名为
null
ArgumentNullException 类)。 - 文件夹名过长(PathTooLongException 类)。
- 文件夹仅为冒号“:”(PathTooLongException 类)。
5️⃣ 如何复制、删除和移动文件和文件夹
♈ 场景需求
复制文件和目录。
♊ 解决方案
以下示例演示如何从 System.IO 命名空间使用 System.IO.File、System.IO.Directory、System.IO.FileInfo 和 System.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 中添加引用
- 在菜单栏上,依次选择“项目”、“添加引用”。
此时将显示“引用管理器”对话框。
- 在“程序集”区域,选择“Framework”(如果尚未选择它)。
- 在名称列表中,选择“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");
}
}
前面的源代码示例:
- 使用三个值实例化字符串数组。
- 以 using 声明的形式使用 WriteLines2.txt 的文件路径实例化 StreamWriter,并传入要追加的
true
。 - 等待对 StreamWriter.WriteLineAsync(String)) 的调用完成,该调用将字符串作为追加行写入文件。
♎ 最佳实践
以下情况可能会导致异常:
- InvalidOperationException:文件已存在并且为只读。
- PathTooLongException:路径名可能太长。
- IOException:磁盘可能已满。
使用文件系统时,还有其他可能会导致异常的情况,因此最好进行防御性编程。
8️⃣ 如何读取文本文件中的内容
♈ 场景需求
通过使用 System.IO.File 类的 ReadAllText 和 ReadAllLines 静态方法来确定文本文件的内容。
♊ 解决方案
示例
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();
♎ 最佳实践
以下情况可能会导致异常:
- 文件可能不存在。
⭐写在结尾:文章中出现的任何错误请大家批评指出,一定及时修改。
希望写在这里的小伙伴能给个三连支持!