C#中常用I/O流介绍、 FileStream类及FileMode、FileAccess、FileShare

原文链接:https://zhuanlan.zhihu.com/p/558000060?utm_id=0

1、流的含义:

流可以视为一组连续的一维数据,包含开头和结尾,并且其中的游标指示了流的当前位置。抽象基类 Stream支持读取和写入字节。

2、流涉及三个基本操作:

读取 :将数据从流传输到数据结构(如字节数组)中。
写入 : 将数据从数据源传输到流。
查找 :对流中的当前位置进行查询和修改。

3、常见的流

C#中由许多类型的流(14种派生类),但是在处理文件输入/输出时,最重要的类型为FileStream类,它提供了读取或写入文件的方式。

C#中常见的流:

  • FileStream: 用于对文件进行读取和写入操作。
  • IsolatedStorageFileStream:用于对独立存储中的文件进行读取或写入操作。
  • MemoryStream:用于作为后备存储对内存进行读取和写入操作,读取速度比FileStream快。
  • BufferedStream :用于改进读取和写入操作的性能。
  • NetworkStream: 用于通过网络套接字进行读取和写入。
  • PipeStream: 用于通过匿名和命名管道进行读取和写入。
  • CryptoStream :用于将数据流链接到加密转换。

4、先总结一下FileMode、FileAccess、FileShare

1.FileMode 指定操作系统打开文件的方式
FileMode 参数控制文件是覆盖、创建、打开还是某种组合。 用于 Open 打开现有文件。 若要追加到文件,请使用 Append。 若要截断文件或创建文件(如果不存在),请使用 Create。

Append 若存在文件,则打开该文件并查找到文件尾,或者创建一个新文件。 FileMode.Append 只能与 FileAccess.Write 一起使用。

Create 指定操作系统应创建新文件。 如果此文件已存在,则会将其覆盖。
CreateNew 指定操作系统应创建新文件, 这需要 Write权限。
Open 指定操作系统应打开现有文件。
OpenOrCreate 指定操作系统应打开文件(如果文件存在);否则,应创建新文件。
Truncate 指定操作系统应打开现有文件。 该文件被打开时,将被截断为零字节大小。
2.FileAccess 定义文件的读取、写入或读/写访问权限的常量
Read 对文件的读访问。 可从文件中读取数据。 与 Write 组合以进行读写访问。
ReadWrite 对文件的读写访问权限。 可从文件读取数据和将数据写入文件。
Write 文件的写访问。 可将数据写入文件。 与 Read 组合以进行读写访问。
3.FileShare包含用于控制其他 FileStream 对象对同一文件可以具有的访问类型的常数。
Delete 允许随后删除文件。
Inheritable 使文件句柄可由子进程继承。 Win32 不直接支持此功能。
None 谢绝共享当前文件。 文件关闭前,打开该文件的任何请求(由此进程或另一进程发出的请求)都将失败。
Read 允许随后打开文件读取。 如果未指定此标志,则文件关闭前,任何打开该文件以进行读取的请求(由此进程或另一进程发出的请求)都将失败。 但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。
ReadWrite 允许随后打开文件读取或写入。 如果未指定此标志,则文件关闭前,任何打开该文件以进行读取或写入的请求(由此进程或另一进程发出)都将失败。 但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。
Write 允许随后打开文件写入。 如果未指定此标志,则文件关闭前,任何打开该文件以进行写入的请求(由此进程或另一进过程发出的请求)都将失败。 但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。
3 FileStream类
为文件提供 Stream,既支持同步读写操作,也支持异步读写操作。

3.1 常用构造方法、属性和方法
构造方法、属性和方法 描述
FileStream(String, FileMode, FileAccess, FileShare, Int32, FileOptions) 构造方法,使用指定的路径、创建模式、读/写和共享权限、其他 FileStreams 可以具有的对此文件的访问权限、缓冲区大小和附加文件选项初始化 FileStream类的新实例。
CanRead 如果流支持读取,则为 true;如果流已关闭或是通过只写访问方式打开的,则为 false
CanSeek 该值指示当前流是否支持查找
CanTimeout 该值确定当前流是否可以超时
IsAsync FileStream 是异步打开还是同步打开的。
Length 获取流的长度(以字节为单位)
Name 获取 FileStream 中已打开的文件的绝对路径。
Position 获取或设置此流的当前位置。
BeginRead(Byte[], Int32, Int32, AsyncCallback, Object) 开始异步读操作。Byte[]:读取存入数组中,第一个Int32:数组开始读取的位置,第二个int32:数组最大的长度。AsyncCallback:异步处理后回调的方法(回调可理解为:B的方法在被A触发的情况下去调用了A的方法。)
Close() 关闭当前流并释放与之关联的所有资源(如套接字和文件句柄)。
CopyTo(Stream, Int32) 使用指定的缓冲区大小,从当前流中读取字节并将其写入到另一流中。Stream:复制到的流,Int32:缓冲区的大小。
Dispose() 释放由 Stream使用的所有资源。
Lock(Int64, Int64) 防止其他进程读取或写入。第一个Int64要锁定的范围的起始处、第二个Int64要锁定的范围。
Read(Byte[], Int32, Int32) 从流中读取字节块并将该数据写入给定缓冲区中。其中:第一个int32中的字节偏移量,将在此处放置读取的字节,第二个int32最多读取的字节数。
Read(Span< Span >) 从当前文件流中读取字节序列,并在该文件流中按照读取的字节数提升位置。
ReadByte() 从文件中读取一个字节,并将读取位置提升一个字节。
Seek(Int64, SeekOrigin) 将该流的当前位置设置为给定值。Int64:参数的字节偏移量offset。SeekOrigin :类型的值,将开始位置、结束位置或当前位置指定为 offset 的参考点。有三个值:Begin(从流的起始位置开始跳跃) Current(继续在当前的Position位置上进行跳跃) End(直接跳到结尾处)。如果 offset 为负,则需要在由指定的字节数之前指定的新位置 origin offset 。 如果 offset 为零 (0) ,则新位置需要是指定的位置 origin 。 如果 offset 为正,则需要在由指定的字节数后跟随新位置 origin offset 。例如:aFile.Seek(-5,SeekOrigin.End); 从文件的末尾向前查找五个字节。
ToString() 返回表示当前对象的字符串。
WriteByte(Byte) 一个字节写入文件流中的当前位置。
Write(Byte[], Int32, Int32) 将字节块写入文件流
Flush(Boolean) 清除此流的缓冲区,将所有缓冲数据都写入到文件中,并且也清除所有中间文件缓冲区。
3.2 代码示例

public static void Main()
{
string path = @"G:\Desktop\archive1\MyTest.txt";
// 如果文件存在则删除文件
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 < 124; i++)
{
AddText(fs, Convert.ToChar(i).ToString());
}
}
//打开流并读取
using (FileStream fs = File.OpenRead(path))
{
//每一次读取字节的长度
byte[] b = new byte[2];
//将该流的当前位置设置为给定值,从流尾向前读五个字节
fs.Seek(-5, SeekOrigin.End);
//给定字节编码格式
UTF8Encoding temp = new UTF8Encoding(true);
while (fs.Read(b, 0, b.Length) > 0)
{
Console.Write(temp.GetString(b)+" ");
Console.WriteLine();
}
Console.WriteLine(fs.Name);
}
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{ //
UTF8Encoding temp = new UTF8Encoding(true);
for (int i = 0; i < fs.Length; i++)
{
byte[] bytes = new byte[1];
bytes[0] = (byte)fs.ReadByte();
Console.Write(temp.GetString(bytes) +" ");
}
if (fs.CanRead)
{
Console.WriteLine("可读");
}
else
{
Console.WriteLine("不可读");
}
}
}
private static void AddText(FileStream fs, string value)
{
//给定编码格式的字节数组
byte[] info = new UTF8Encoding(true).GetBytes(value);
//写入字节数组
fs.Write(info, 0, info.Length);
}

 运行结果:

 

posted @ 2024-04-10 11:45  yinghualeihenmei  阅读(32)  评论(0编辑  收藏  举报