C#— —文件操作

本文主要介绍C#中的一些文件操作,并介绍如何进行文件读写。

1. 文件信息类

1.1 File和FileInfo类

  • File:提供关于文件创建、复制、删除、移动以及打开操作的静态方法,并且帮助创建FileStream对象;
  • FileInfo:提供文件属性,以及关于文件创建、复制、删除、移动以及打开操作的实例方法,并且帮助创建FileStream对象;该类不可以被继承。

案例,以File为例,进行文件的操作:

string path = @"D:\a.txt";           // 文件路径
if (!File.Exists(path))				 // 如果文件不存在,则创建该文件
{
    File.Create(path).Close();       //  重点!!!
}

File.AppendAllText(path, "hello world");   // 以追加的方式向指定的文件中写入文本

在这里插入图片描述

重点:为什么在新建文件后还需要调用Close()方法呢?

如果我们去掉Close()方法,直接新建文件然后向文件写入文本,则会产生如下错误:

文件“D:\a.txt”正由另一进程使用,因此该进程无法访问此文件。

原因是File.Create()后,返回结果是FileStream,如果不关闭这个文件流,则这个文件就会被一直占用着,导致另外的进程无法访问。

FileInfo的使用如下:

string path = @"D:\b.txt";
FileInfo fileInfo = new FileInfo(path);
if (!fileInfo.Exists)
{
    fileInfo.Create().Close();
}
// FileInfo 没有提供直接向文件写入内容的方法

1.2 Directory和DirectoryInfo类

  • Directory:提供创建、移动和便利目录的静态方法,该类不可以被继承;
  • DirectoryInfo:提供创建、移动和便利目录的实例方法,该类不可以被继承;

案例,演示Directory的使用:

string directoryPath = @"D:\test";     // 目录路径
if (!Directory.Exists(directoryPath))  // 如果目录不存在,则创建
{
    Directory.CreateDirectory(directoryPath);
}
//获取指定目录下的所有文件名,非递归(不包括子目录中的文件名)
string[] fileNames = Directory.GetFiles(directoryPath); 
foreach(string filename in fileNames)
{
    Console.WriteLine(filename);
}

// 获取指定目录下的子目录名称
string[] directoryNames = Directory.GetDirectories(directoryPath); 
foreach(string directoreName in directoryNames)
{
    Console.WriteLine(directoreName);
}

在这里插入图片描述

1.3 DriveInfo类

  • DriveInfo:提供访问驱动信息的入口
DriveInfo[] drives = DriveInfo.GetDrives();      // 获取所有的驱动实例
foreach(DriveInfo drive in drives)
{
    Console.WriteLine("Drive Name:{0}",drive.Name);     // 驱动器名
    Console.WriteLine("Drive Type:{0}", drive.DriveType);   // 驱动器类型

    if (drive.IsReady)
    {
        Console.WriteLine("  Volume label: {0}", drive.VolumeLabel);
        Console.WriteLine("  File system: {0}", drive.DriveFormat);     // 文件系统类型
        Console.WriteLine(
            "  Available space to current user:{0, 15} bytes",
            drive.AvailableFreeSpace);           // 当前用户可用空间大小

        Console.WriteLine(
            "  Total available space:          {0, 15} bytes",
            drive.TotalFreeSpace);              // 可用空间大小

        Console.WriteLine(
            "  Total size of drive:            {0, 15} bytes ",
            drive.TotalSize);                   // 总大小 
    }
}

在这里插入图片描述

2. 流

流(Stream)可以理解为内存中的字节序列。Stream是所有流的抽象基类,每个具体的存储实体都可以通过Stream派生类来实现,如FileStream类就表示文件这种存储实体。

流涉及三种几乎操作:

  • 对流进行读取:将流中的数据读取出来;
  • 对流进行写入:把数据写入流中;
  • 对流进行查找:对流内的当前位置进行查询和修改;

流操作的是字节数据。

我们以FileStream为例,来演示流的操作:

string filePath = @"D:\stream.txt";
FileStream fileStream = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);

string msg = "hello world\n你好,世界";
byte[] msgBytes = Encoding.Default.GetBytes(msg);
Console.WriteLine("开始向流中写入数据...");
fileStream.Write(msgBytes, 0, msgBytes.Length);

fileStream.Seek(0,SeekOrigin.Begin);

byte[] readBytes = new byte[msgBytes.Length];
fileStream.Read(readBytes,0,readBytes.Length);
string readStr = Encoding.Default.GetString(readBytes);
Console.WriteLine("从流中读取数据...\n{0}",readStr);

fileStream.Close();

说明:

  • 在打开流时,要注意文件权限与文件的打开方式:

    文件的权限包括读、写以及读写

    public enum FileAccess
    {
        // 对文件的读访问。 可从文件中读取数据。 与 Write 组合以进行读写访问。
        Read = 1,
        // 文件的写访问。 可将数据写入文件。 与 Read 组合以进行读写访问。
        Write = 2,
        // 对文件的读写访问权限。 可从文件读取数据和将数据写入文件。
        ReadWrite = 3
    }
    

    文件的打开方式在FileMode枚举中,包括CreateNewCreateOpenOpenOrCreateTruncateAppend

    public enum FileMode
    {
        // 指定操作系统应创建新文件。 这需要 System.Security.Permissions.FileIOPermissionAccess.Write 权限。
        // 如果文件已存在,则将引发 System.IO.IOException异常。
        CreateNew = 1,
        // 指定操作系统应创建新文件。 如果文件已存在,它将被覆盖。 这需要 System.Security.Permissions.FileIOPermissionAccess.Write
        // 权限。 FileMode.Create 等效于这样的请求:如果文件不存在,则使用 System.IO.FileMode.CreateNew;否则使用 System.IO.FileMode.Truncate。
        // 如果该文件已存在但为隐藏文件,则将引发 System.UnauthorizedAccessException异常。
        Create = 2,
        // 指定操作系统应打开现有文件。 打开文件的能力取决于 System.IO.FileAccess 枚举所指定的值。 如果文件不存在,引发一个 System.IO.FileNotFoundException异常
        Open = 3,
        // 指定操作系统应打开文件(如果文件存在);否则,应创建新文件。 
        // 如果用 FileAccess.Read 打开文件,则需要 System.Security.Permissions.FileIOPermissionAccess.Read权限。
        // 如果文件访问为 FileAccess.Write,则需要 System.Security.Permissions.FileIOPermissionAccess.Write权限。
        // 如果用 FileAccess.ReadWrite 打开文件,则同时需要 System.Security.Permissions.FileIOPermissionAccess.Read
        // 和 System.Security.Permissions.FileIOPermissionAccess.Write权限。
        OpenOrCreate = 4,
        // 指定操作系统应打开现有文件。 该文件被打开时,将被截断为零字节大小。 这需要 System.Security.Permissions.FileIOPermissionAccess.Write 权限
        // 尝试从使用 FileMode.Truncate 打开的文件中进行读取将导致 System.ArgumentException 异常。
        Truncate = 5,
        //  若存在文件,则打开该文件并查找到文件尾,或者创建一个新文件。 这需要 System.Security.Permissions.FileIOPermissionAccess.Append权限。
        //  FileMode.Append 只能与 FileAccess.Write 一起使用。 试图查找文件尾之前的位置时会引发 System.IO.IOException异常,
        //  并且任何试图读取的操作都会失败并引发 System.NotSupportedException 异常。
        Append = 6
    }
    

    关于文件的权限和文件的读取方式,如源码中的注释。在打开流时,一定要注意打开文件的方式及权限,否则可能会操作失败。

  • fileStream.Seek(long offset, SeekOrigin origin)方法:该方法的作用时重置流指针的位置,其包含两个参数。

    public enum SeekOrigin
    {
        // 指定流的开始位置。
        Begin = 0,
        // 指定流中的当前位置。
        Current = 1,
        // 指定流的结束位置。
        End = 2
    }
    

    关于Seek()的用法,如下图所示:

在这里插入图片描述

表示流指针从SeekOrigin所表示的位置开始,偏移offset后,流指针到达新位置。offset正数代表向前偏移,负数代表往后偏移。

  • 流操作的数据都是字节数据,所以需要将字符串等数据转换成字节数组;

  • 操作完成后,需要调用Close()方法关闭流;

3. 读写器

由于流操作的是字节数组,不太方便,所以在流的基础上,出现了读写器。读写器通常是成对出现的:一个从流中读取数据,一个用于向流中写入数据。不同类型的读写器分别适用于处理字符串、二进制数据和流等。

字符串读写器:StringReaderStringWriter

二进制读写器:BinaryReaderBinaryWriter

流读写器:StreamReaderStreamWriter

本例演示如何StreamReader从文件中读取内容:

string filePath = @"D:\stream.txt";
FileStream fileStream = File.OpenRead(filePath);
// 打开流读取器
StreamReader streamReader = new StreamReader(fileStream,Encoding.UTF8);
// 读取文件的全部内容
string msg = streamReader.ReadToEnd();
Console.WriteLine(msg);
// 关闭资源
streamReader.Close();
fileStream.Close();

在这里插入图片描述

注意:一定要注意文件的编码格式,否则读取出来的内容会乱码。

参考资料

[1] https://docs.microsoft.com/en-us/dotnet/api/system.io?view=net-5.0

[2] https://blog.csdn.net/jazywoo123/article/details/6981253

[3] StringReader:https://docs.microsoft.com/en-us/dotnet/api/system.io.stringreader?view=net-5.0

[4] StreamReader:https://docs.microsoft.com/en-us/dotnet/api/system.io.streamreader?view=net-5.0

[5] 李志 《Learning hard c#学习笔记》

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值