System.IO下的Stream类是所有数据流的基类,当用户对数据进行逐字节操作时,首先需要将数据转换为数据流。C#中有许多类型的流,但在处理文件输入/输出时,最主要的类型为FileStream类。其他还有StreamReader类、StreamWriter类、BinaryWriter类和BinaryReader类。在处理文件I/O时还包括BufferedStream、CryptoStream、MemoryStream、NetworkStream等。
流是一个拥有传输数据的对象,数据的传输一般有以下两种方法:
- 数据从外部源传输到程序中,这种流称为读取流。
- 数据从程序中传输到外部源,这种流称为写入流。
流一般具有以下几个基本操作:
- 读(Read)操作:读取流对象中的数据,并把它存放到另一个数据结构中。
- 写(Write)操作:从另一种数据结构中读取数据并存放到流对象中。
- 搜索(Seek)操作:从流中的当前位置开始搜索定位到指定的位。
一、文件流 类(FileStream 类)
1、定义
为文件提供 Stream,既支持同步读写操作,也支持异步读写操作。即用来实现对文件的读取和写入
- 命名空间:System.IO
- 程序集:mscorlib.dll
- 继承:Object→MarshalByRefObject→Stream→FileStream
- 派生:System.IO.IsolatedStorage.IsolatedStorageFileStream
- 属性:ComVisibleAttribute
[System.Runtime.InteropServices.ComVisible(true)]
public class FileStream : System.IO.Stream
使用 类可以读取、写入、打开和关闭文件系统上的文件,以及操作其他与文件相关的操作系统句柄,包括管道、标准输入和 FileStream 标准输出。
2、FileStream 类的构造函数
FileStream(IntPtr, FileAccess) |
已过时。 使用指定的读/写权限为指定的文件句柄初始化 FileStream 类的新实例。
|
FileStream(IntPtr, FileAccess, Boolean) |
已过时。 使用指定的读/写权限和 FileStream 实例所属权为指定的文件句柄初始化 FileStream 类的新实例。
|
FileStream(IntPtr, FileAccess, Boolean, Int32) |
已过时。 使用指定的读/写权限、FileStream 实例所属权和缓冲区大小为指定的文件句柄初始化 FileStream 类的新实例。
|
FileStream(IntPtr, FileAccess, Boolean, Int32, Boolean) |
已过时。 使用指定的读/写权限、FileStream 实例所属权、缓冲区大小和同步或异步状态为指定的文件句柄初始化 FileStream 类的新实例。
|
FileStream(SafeFileHandle, FileAccess) | 使用指定的读/写权限为指定的文件句柄初始化 FileStream 类的新实例。 |
FileStream(SafeFileHandle, FileAccess, Int32) | 使用指定的读/写权限和缓冲区大小为指定的文件句柄初始化 FileStream 类的新实例。 |
FileStream(SafeFileHandle, FileAccess, Int32, Boolean) | 使用指定的读/写权限、缓冲区大小和同步或异步状态为指定的文件句柄初始化 FileStream 类的新实例。 |
FileStream(String, FileMode) | 使用指定的路径和创建模式初始化 FileStream 类的新实例。 |
FileStream(String, FileMode, FileAccess) | 使用指定的路径、创建模式和读/写权限初始化 FileStream 类的新实例。 |
FileStream(String, FileMode, FileAccess, FileShare) | 使用指定的路径、创建模式、读/写权限和共享权限创建 FileStream 类的新实例。 |
FileStream(String, FileMode, FileAccess, FileShare, Int32) | 用指定的路径、创建模式、读/写及共享权限和缓冲区大小初始化 FileStream 类的新实例。 |
FileStream(String, FileMode, FileAccess, FileShare, Int32, Boolean) | 使用指定的路径、创建模式、读/写和共享权限、缓冲区大小和同步或异步状态初始化 FileStream 类的新实例。 |
FileStream(String, FileMode, FileAccess, FileShare, Int32, FileOptions) | 使用指定的路径、创建模式、读/写和共享权限、其他 FileStreams 可以具有的对此文件的访问权限、缓冲区大小和附加文件选项初始化 FileStream 类的新实例。 |
FileStream(String, FileMode, FileSystemRights, FileShare, Int32, FileOptions) | 使用指定的路径、创建模式、访问权限和共享权限、缓冲区大小和附加文件选项初始化 FileStream 类的新实例。 |
FileStream(String, FileMode, FileSystemRights, FileShare, Int32, FileOptions, FileSecurity) | 使用指定的路径、创建模式、访问权限和共享权限、缓冲区大小、附加文件选项、访问控制和审核安全初始化 FileStream 类的新实例。 |
3、FileStream 类的属性
CanRead | 获取一个值,该值指示当前流是否支持读取。 |
CanSeek | 获取一个值,该值指示当前流是否支持查找。 |
CanTimeout | 获取一个值,该值确定当前流是否可以超时。(继承自 Stream) |
CanWrite | 获取一个值,该值指示当前流是否支持写入。 |
Handle |
已过时。获取当前 FileStream 对象所封装文件的操作系统文件句柄。
|
IsAsync | 获取一个值,它指示 FileStream 是异步打开还是同步打开的。 |
Length | 获取流的长度(以字节为单位)。 |
Name | 获取 FileStream 中已打开的文件的绝对路径。 |
Position | 获取或设置此流的当前位置。 |
ReadTimeout | 获取或设置一个值(以毫秒为单位),该值确定流在超时前将尝试读取的时间。(继承自 Stream) |
SafeFileHandle | 获取 SafeFileHandle 对象,它代表当前 FileStream 对象所封装的文件的操作系统文件句柄。 |
WriteTimeout | 获取或设置一个值(以毫秒为单位),该值确定流在超时前将尝试写入多长时间。(继承自 Stream) |
4、FileStream 类的方法
BeginRead(Byte[], Int32, Int32, AsyncCallback, Object) | 开始异步读操作。 请考虑改用 ReadAsync(Byte[], Int32, Int32, CancellationToken)。 |
BeginWrite(Byte[], Int32, Int32, AsyncCallback, Object) | 开始异步写操作。 请考虑改用 WriteAsync(Byte[], Int32, Int32, CancellationToken)。 |
Close() | 关闭当前流并释放与之关联的所有资源(如套接字和文件句柄)。 不直接调用此方法,而应确保流得以正确释放。(继承自 Stream) |
CopyTo(Stream) | 从当前流中读取字节并将其写入到另一流中。(继承自 Stream) |
CopyTo(Stream, Int32) | 使用指定的缓冲区大小,从当前流中读取字节并将其写入到另一流中。(继承自 Stream) |
CopyToAsync(Stream) | 从当前流中异步读取字节并将其写入到另一个流中。(继承自 Stream) |
CopyToAsync(Stream, CancellationToken) | 通过指定的取消令牌,从当前流中异步读取字节并将其写入到另一个流中。(继承自 Stream) |
CopyToAsync(Stream, Int32) | 使用指定的缓冲区大小,从当前流中异步读取字节并将其写入到另一流中。(继承自 Stream) |
CopyToAsync(Stream, Int32, CancellationToken) | 使用指定的缓冲区大小和取消令牌,从当前流中异步读取字节并将其写入到另一个流中。(继承自 Stream) |
CreateObjRef(Type) | 创建一个对象,该对象包含生成用于与远程对象进行通信的代理所需的全部相关信息。(继承自 MarshalByRefObject) |
CreateWaitHandle() |
已过时。 分配 WaitHandle 对象。(继承自 Stream)
|
Dispose() | 释放由 Stream 使用的所有资源。(继承自 Stream) |
Dispose(Boolean) | 释放由 FileStream 占用的非托管资源,还可以另外再释放托管资源。 |
DisposeAsync() | 异步释放 Stream 使用的非托管资源。(继承自 Stream) |
EndRead(IAsyncResult) | 等待挂起的异步读操作完成。 (请考虑改用 ReadAsync(Byte[], Int32, Int32, CancellationToken)。) |
EndWrite(IAsyncResult) | 结束异步写入操作,在 I/O 操作完成之前一直阻止。 (请考虑改用 WriteAsync(Byte[], Int32, Int32, CancellationToken)。) |
Equals(Object) | 确定指定对象是否等于当前对象。(继承自 Object) |
Finalize() | 确保垃圾回收器回收 FileStream 时释放资源并执行其他清理操作。 |
Flush() | 清除此流的缓冲区,使得所有缓冲数据都写入到文件中。 |
Flush(Boolean) | 清除此流的缓冲区,将所有缓冲数据都写入到文件中,并且也清除所有中间文件缓冲区。 |
FlushAsync() | 异步清除此流的所有缓冲区并导致所有缓冲数据都写入基础设备中。(继承自 Stream) |
FlushAsync(CancellationToken) | 异步清理此流的所有缓冲区,导致所有缓冲数据都写入基础设备,并且监控取消请求。(继承自 Stream) |
GetAccessControl() | 获取 FileSecurity 对象,该对象封装当前 FileStream 对象所描述的文件的访问控制列表 (ACL) 项。 |
GetHashCode() | 作为默认哈希函数。(继承自 Object) |
GetLifetimeService() | 检索控制此实例的生存期策略的当前生存期服务对象。(继承自 MarshalByRefObject) |
GetType() | 获取当前实例的 Type。(继承自 Object) |
InitializeLifetimeService() | 获取生存期服务对象来控制此实例的生存期策略。(继承自 MarshalByRefObject) |
Lock(Int64, Int64) | 防止其他进程读取或写入 FileStream。 |
MemberwiseClone() | 创建当前 Object 的浅表副本。(继承自 Object) |
MemberwiseClone(Boolean) | 创建当前 MarshalByRefObject 对象的浅表副本。(继承自 MarshalByRefObject) |
ObjectInvariant() | 提供对 Contract 的支持。(继承自 Stream) |
Read(Byte[], Int32, Int32) | 从流中读取字节块并将该数据写入给定缓冲区中。 |
Read(Span<Byte>) | 当在派生类中重写时,从当前流读取字节序列,并将此流中的位置提升读取的字节数。(继承自 Stream) |
ReadAsync(Byte[], Int32, Int32) | 从当前流异步读取字节序列,并将流中的位置提升读取的字节数。(继承自 Stream) |
ReadAsync(Byte[], Int32, Int32, CancellationToken) | 从当前流异步读取字节的序列,将流中的位置提升读取的字节数,并监视取消请求。(继承自 Stream) |
ReadAsync(Memory<Byte>, CancellationToken) | 从当前流异步读取字节的序列,将流中的位置提升读取的字节数,并监视取消请求。(继承自 Stream) |
ReadByte() | 从文件中读取一个字节,并将读取位置提升一个字节。 |
Seek(Int64, SeekOrigin) | 将该流的当前位置设置为给定值。 |
SetAccessControl(FileSecurity) | 将 FileSecurity 对象所描述的访问控制列表 (ACL) 项应用于当前 FileStream 对象所描述的文件。 |
SetLength(Int64) | 将该流的长度设置为给定值。 |
ToString() | 返回表示当前对象的字符串。(继承自 Object) |
Unlock(Int64, Int64) | 允许其他进程访问以前锁定的某个文件的全部或部分。 |
Write(Byte[], Int32, Int32) | 将字节块写入文件流。 |
Write(ReadOnlySpan<Byte>) | 当在派生类中重写时,向当前流中写入字节序列,并将此流中的当前位置提升写入的字节数。(继承自 Stream) |
WriteAsync(Byte[], Int32, Int32) | 将字节序列异步写入当前流,并将流的当前位置提升写入的字节数。(继承自 Stream) |
WriteAsync(Byte[], Int32, Int32, CancellationToken) | 将字节的序列异步写入当前流,将该流中的当前位置向前移动写入的字节数,并监视取消请求。(继承自 Stream) |
WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) | 将字节的序列异步写入当前流,将该流中的当前位置向前移动写入的字节数,并监视取消请求。(继承自 Stream) |
WriteByte(Byte) | 一个字节写入文件流中的当前位置。 |
二、FileMode 枚举
1、定义
指定操作系统打开文件的方式。
- 命名空间:System.IO
- 程序集:mscorlib.dll
- 继承:Object→ValueType→Enum→FileMode
- 属性:SerializableAttribute ComVisibleAttribute
2、FileMode 枚举的字段
Append | 6 | 若存在文件,则打开该文件并查找到文件尾,或者创建一个新文件。 这需要 Append 权限。 FileMode.Append 只能与 FileAccess.Write 一起使用。 试图查找文件尾之前的位置时会引发 IOException 异常,并且任何试图读取的操作都会失败并引发 NotSupportedException 异常。 |
Create | 2 | 指定操作系统应创建新文件。 如果此文件已存在,则会将其覆盖。 这需要 Write 权限。 FileMode.Create 等效于这样的请求:如果文件不存在,则使用 CreateNew;否则使用 Truncate。 如果该文件已存在但为隐藏文件,则将引发 UnauthorizedAccessException异常。 |
CreateNew | 1 | 指定操作系统应创建新文件。 这需要 Write 权限。 如果文件已存在,则将引发 IOException异常。 |
Open | 3 | 指定操作系统应打开现有文件。 打开文件的能力取决于 FileAccess 枚举所指定的值。 如果文件不存在,引发一个 FileNotFoundException 异常。 |
OpenOrCreate | 4 | 指定操作系统应打开文件(如果文件存在);否则,应创建新文件。 如果用 FileAccess.Read 打开文件,则需要 Read权限。 如果文件访问为 FileAccess.Write,则需要 Write权限。 如果用 FileAccess.ReadWrite 打开文件,则同时需要 Read 和 Write权限。 |
Truncate | 5 | 指定操作系统应打开现有文件。 该文件被打开时,将被截断为零字节大小。 这需要 Write 权限。 尝试从使用 FileMode.Truncate 打开的文件中进行读取将导致 ArgumentException 异常。 |
三、FileAccess 枚举
1、定义
定义文件的读取、写入或读/写访问权限的常量。此枚举支持其成员值的按位组合。
- 命名空间:System.IO
- 程序集:mscorlib.dll
- 继承:Object→ValueType→Enum→FileAccess
- 属性:FlagsAttribute、SerializableAttribute ComVisibleAttribute
[System.Flags]
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public enum FileAccess
2、FileAccess 枚举的字段
Read | 1 | (只读)对文件的读访问。 可从文件中读取数据。 与 Write 组合以进行读写访问。 |
ReadWrite | 3 | (读/写)对文件的读写访问权限。 可从文件读取数据和将数据写入文件。 |
Write | 2 | (只写)文件的写访问。 可将数据写入文件。 与 Read 组合以进行读写访问。 |
备注:在没有FileAccess枚举的参数版本中,默认值使用的是ReadWrite模式。
四、示例
using System;
using System.IO;
using System.Text;
namespace _20220901_1
{
class Test
{
public static void Main()
{
string path = @"d:\MyTest.txt";
// 如果文件存在,请删除该文件。
if (File.Exists(path))
{
File.Delete(path);
}
//创建该文件。
using (FileStream fs = File.Create(path))
{
AddText(fs, "这是一个文本,");
AddText(fs, "这是一个更多的文本,");
AddText(fs, "\r\n这是一条新的线");
AddText(fs, "\r\n\r\n以下是字符的子集:\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);
while (fs.Read(b, 0, b.Length) > 0)
{
Console.WriteLine(temp.GetString(b));
}
}
}
private static void AddText(FileStream fs, string value)
{
byte[] info = new UTF8Encoding(true).GetBytes(value);
fs.Write(info, 0, info.Length);
}
}
}