流的类型
文件流(FileStream)
FileStream流继承于Stream类,代表一个文件流,使用FileStream类可以对文件进行读取、写入、打开和关闭操作
常用构造函数:
public FileStream(string path, FileMode mode, FileAccess access);
参数说明:
path指明文件所在的路径信息;
mode是FileMode的枚举值,表示文件打开或创建的方式,含义如下:
- CreateNew:指定操作系统应创建新文件,如果文件已经存在,则引发IOException;
- Create:指定操作系统应创建新文件,如果文件已经存在,它将被覆盖;
- Open:指定操作系统应打开现有文件,如果文件不存在,则引发FileNotFoundException;
- OpenOrCreate:指定操作系统应打开文件,如果文件不存在,则创建新文件;
- Truncate:指定操作系统应打开现有文件,文件一旦打开,就将截断为零字节大小;
- Append:打开先有文件并把Position设置至文件尾,如果文件不存在将创建新文件。Append只能同FileAccess.Write一起使用;
access是FileAccess的枚举值,它控制对文件的访问权限,含义如下:
- Read:打开文件用于只读;
- Write:打开文件用于只写;
- ReadWrite:打开文件,用于读写;
内存流(MemoryStream)
MemoryStream表示的是保存在内存中的数据流,由内存流封装的数据可以在内存中直接访问。内存一般用于暂时缓存数据以降低应用程序对临时缓冲区(临时缓冲区)和临时文件的需要。
既然字节数组也在内存中存储,为什么还要引入内存流的概念呢?这是因为内存流和字节数组虽然都位于程序缓冲区,但是具有不同特性。内存流相对于字节数组而言,具有流特有的特性,并且容量可自动增长,在数据加密以及对长度不定的数据进行缓存等场合,使用内存流比较方便。
MemoryStream构造函数:
public MemoryStream();该构造函数初始分配的容量大小为0,随着数据的不断写入,其容量可以不断地自动扩展。
public MemoryStream(byte[] buffer);根据字节数组buffer初始化,实例的容量大小规定为字节数组的长度。
public MemoryStream(int capacity);容量固定为capacity。
网络流(NetWorkStream)
网络流的意思是数据在网络的各个位置之间是以连续的字节形式传输的,NetWorkStream只能用于面向连接的套接字。
流的装饰器
除了以上流,还有更多的流,比如压缩流、加密流,这些流不仅有Stream的所有特征,还有自己的个性。它们不仅继承Stream类,还引用Stream类。这些通过"装饰器模式"来实现的流包括:BufferedStream, DeflateStream, GZipStream, CryptoStream, AuthenticateStream.
GZipStream
//压缩 压缩后 打开文本文件是 一个乱码
static void simple2_1()
{
string s = "好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好";
for (int i = 0; i < 15; i++)
{
s += s;
}//设置一个字符串,因为要足够大,才能看得出压缩的效果,所有使用for语句
using (FileStream fs = File.OpenWrite("C:\1.txt"))//定义一个打文件流
{
using (GZipStream gz = new GZipStream(fs, CompressionMode.Compress))//定义一个压缩流
{
byte[] bytes = Encoding.UTF8.GetBytes(s);//把文字转换成字节
gz.Write(bytes, 0, bytes.Length);//写入文件
}
}
}
//解压
static void simple2_2()
{
using (FileStream fs = new FileStream("c:\1.txt", FileMode.Open))//定义打开文件流
{
using (GZipStream zp = new GZipStream(fs, CompressionMode.Decompress))//对文件流进行解密
{
byte[] b = new byte[1024];
int readbyte=0;
using (FileStream outstream = new FileStream("c:\2.txt", FileMode.Create))//新建一个文件流用于输出
{
while((readbyte=zp.Read(b,0,1024))>0)
{
outstream.Write(b,0,readbyte);
}
}
}
}
}
分批复制
如果文件比较大(>2G),那就需要分批复制了。
static async Task Main(string[] args)
{
string path = Directory.GetCurrentDirectory();
string fromFile = Path.Combine(path, "from.txt");
string toFile = Path.Combine(path, "to.txt");
byte[] buffer = null;
FileStream toFS = new FileStream(toFile, FileMode.Create, FileAccess.Write);
FileStream fromFS = new FileStream(fromFile, FileMode.Open, FileAccess.Read);
int readLength = 0;
do
{
buffer = new byte[1024];
readLength = fromFS.Read(buffer, 0, buffer.Length);
toFS.Write(buffer, 0, readLength);
} while (readLength > 0);
fromFS.Flush();
fromFS.Dispose();
toFS.Flush();
toFS.Dispose();
Console.ReadKey();
}
BinaryFormatter
将对象序列化为二进制数组
/// <summary>
/// 将一个object对象序列化,返回一个byte[]
/// </summary>
/// <param name="obj">能序列化的对象</param>
/// <returns></returns>
public static byte[] ObjectToBytes(object obj)
{
using (MemoryStream ms = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
return ms.GetBuffer();
}
}
/// <summary>
/// 将一个序列化后的byte[]数组还原
/// </summary>
/// <param name="Bytes"></param>
/// <returns></returns>
public static object BytesToObject(byte[] Bytes)
{
using (MemoryStream ms = new MemoryStream(Bytes))
{
IFormatter formatter = new BinaryFormatter();
return formatter.Deserialize(ms);
}
}
BinaryWriter、BinaryReader
BinaryWriter:以二进制形式将基元类型写入流,并支持用特定的编码写入字符串。
BinartReader:用特定的编码将基元数据类型读作二进制值。
案例:
public class PropertiesSerializer : IDataSerializer<AuthenticationProperties>
{
private const int FormatVersion = 1;
/// <summary>
/// Gets the default instance of <see cref="PropertiesSerializer"/>.
/// </summary>
public static PropertiesSerializer Default { get; } = new PropertiesSerializer();
/// <inheritdoc />
public virtual byte[] Serialize(AuthenticationProperties model)
{
using (var memory = new MemoryStream())
{
using (var writer = new BinaryWriter(memory))
{
Write(writer, model);
writer.Flush();
return memory.ToArray();
}
}
}
/// <inheritdoc />
public virtual AuthenticationProperties? Deserialize(byte[] data)
{
using (var memory = new MemoryStream(data))
{
using (var reader = new BinaryReader(memory))
{
return Read(reader);
}
}
}
/// <inheritdoc />
public virtual void Write(BinaryWriter writer, AuthenticationProperties properties)
{
if (writer == null)
{
throw new ArgumentNullException(nameof(writer));
}
if (properties == null)
{
throw new ArgumentNullException(nameof(properties));
}
writer.Write(FormatVersion);
writer.Write(properties.Items.Count);
foreach (var item in properties.Items)
{
writer.Write(item.Key ?? string.Empty);
writer.Write(item.Value ?? string.Empty);
}
}
/// <inheritdoc />
public virtual AuthenticationProperties? Read(BinaryReader reader)
{
if (reader == null)
{
throw new ArgumentNullException(nameof(reader));
}
if (reader.ReadInt32() != FormatVersion)
{
return null;
}
var count = reader.ReadInt32();
var extra = new Dictionary<string, string?>(count);
for (var index = 0; index != count; ++index)
{
var key = reader.ReadString();
var value = reader.ReadString();
extra.Add(key, value);
}
return new AuthenticationProperties(extra);
}
}