C# Stream(学习笔记)

什么是Stream?

流就是提供字节序列的一般视图
(也有人理解的流是向自然界的河流那样清澈而又美丽,c#中的流也是一样,许多技术或者说核心技术都需要流的帮忙)

什么是字节序列呢?

其实字节序列就是字节对象都被存储为连续的字节序列,字节按照一定的顺序进行排序组成了字节序列
(形象得理解为:一条河中有一条鱼游过,这个鱼就是一个字节,这个字节包括鱼的眼睛,嘴巴,等组成8个二进制,显然这条河就是我们的核心对象:流)

Stream是如何使用的

Stream 类有一个protected 类型的构造函数, 但是它是个抽象类,无法直接如下使用

  1. CanRead: 只读属性,判断该流是否能够读取
  2. CanSeek: 只读属性,判断该流是否支持跟踪查找
  3. CanWrite: 只读属性,判断当前流是否可写
  4. Flush方法比较重要:
    当我们使用流写文件时,数据流会先进入到缓冲区中,而不会立刻写入文件,当执行这个方法后,缓冲区的数据流会立即注入基础流。MSDN中的描述:使用此方法将所有信息从基础缓冲区移动到其目标或清除缓冲区,或者同时执行这两种操作。根据对象的状态,可能需要修改流内的当前位置(例如:在基础流支持查找的情况下即如此)当使StreamWriter 或 BinaryWriter 类时,不要刷新 Stream 基对象。而应使用该类的 Flush 或 Close 方法,此方法确保首先将该数据刷新至基础流,然后再将其写入文件
  5. Length:表示流的长度
  6. Position属性(非常重要):
    虽然从字面中可以看出这个Position属性只是标示了流中的一个位置而已,很多asp.net项目中文件或图片上传中很多朋友会经历过这样一个痛苦:Stream对象被缓存了,导致了Position属性在流中无法找到正确的位置,这点会让人抓狂,其实解决这个问题很简单,聪明的你肯定想到了,其实我们每次使用流前必须将Stream.Position设置成0就行了,但是这还不能根本上解决问题,最好的方法就是用Using语句将流对象包裹起来,用完后关闭回收即可
  7. abstract int Read(byte[] buffer, int offset, int count)方法:
    这个方法包含了3个关键的参数:缓冲字节数组,位移偏量和读取字节个数,每次读取一个字节后会返回一个缓冲区中的总字节数
    第一个参数:这个数组相当于一个空盒子,Read()方法每次读取流中的一个字节将其放进这个空盒子中。(全部读完后便可使用buffer字节数组了)
    第二个参数:表示位移偏量,告诉我们从流中哪个位置(偏移量)开始读取。
    最后一个参数:就是读取多少字节数。
    返回值便是总共读取了多少字节数.
  8. abstract long Seek(long offset, SeekOrigin origin)方法:
    其实Seek方法就是重新设定流中的一个位置,在说明offset参数作用之前大家先来了解下SeekOrigin这个枚举:
    在这里插入图片描述
    如果 offset 为负,则要求新位置位于 origin 指定的位置之前,其间隔相差 offset 指定的字节数。如果 offset 为零 (0),则要求新位置位于由 origin 指定的位置处
    如果 offset 为正,则要求新位置位于 origin 指定的位置之后,其间隔相差 offset 指定的字节数.
    Stream. Seek(-3,Origin.End); 表示在流末端往前数第3个位置
    Stream. Seek(0,Origin.Begin); 表示在流的开头位置
    Stream. Seek(3,Orig`in.Current); 表示在流的当前位置往后数第三个位置
    查找之后会返回一个流中的一个新位置
  9. abstract void Write(byte[] buffer,int offset,int count):
    这个方法包含了3个关键的参数:缓冲字节数组,位移偏量和读取字节个数和read方法不同的是 write方法中的第一个参数buffer已经有了许多byte类型的数据,我们只需通过设置 offset和count来将buffer中的数据写入流中
  10. virtual void Close():
    关闭流并释放资源,在实际操作中,如果不用using的话,别忘了使用完流之后将其关闭;这个方法特别重要,使用完当前流千万别忘记关闭

其它类型流简单的使用

FileStream

/// <summary>
/// 用FileStream1直接写入数据
/// </summary>
static void GetFileStream2() 
{
    string content = @"<?xml version='1.0' encoding='utf-8'?>
<TAS>
<szUTCDate>20200807085759</szUTCDate>
<szTaDomain>POS</szTaDomain>
<szTaType>SA</szTaType>
<szTaOperationType>SALE</szTaOperationType>
<szInfo>0</szInfo>
<bNotPrinted>-1</bNotPrinted>
<lClientID>1</lClientID>
<szExternalClientID>CN</szExternalClientID>
<szClientName>CHINA</szClientName>
<szMode>POSMODE</szMode>
<szSessionID>6190:2:11343:2:20200807</szSessionID>
<szFooterLine1>HAVE A NICE DAY – 祝您购物愉快</szFooterLine1>
<szFooterLine2>美丽购物新捷径</szFooterLine2>
<szFooterLine3>退货规定</szFooterLine3>
<szFooterLine4>所有护肤,彩妆,香水产品, 一经售出,不予退换,过敏问题除外。</szFooterLine4>
<szFooterLine5>2.如使用产品过敏,请凭制定医院证明及原始购物小票办理退货,因化妆品有一定的使</szFooterLine5>
<szFooterLine6 Type='202'>3.门店不接受非本店售出商品的退换货。</szFooterLine6>
< szFooterLine7 Type = '202'> 4.商品退货时需退回相应的赠品,如赠品不能退回将酌情扣除部分退货金额。</ szFooterLine7 >
   </ TAS > ";
    string FilePath = @"E:\开发学习\流的认知\File\test.txt";
    FileStream sterm = new FileStream(FilePath, FileMode.Truncate, FileAccess.Write);
    byte[] byData = Encoding.UTF8.GetBytes(content); //建立一个FileStream要用的字节组
    sterm.Seek(10095, SeekOrigin.Begin); //指定从那个字节读数据
    sterm.Write(byData,0, byData.Length);
    sterm.Close();
    sterm.Dispose();
}

/// <summary>
/// 用FileStream1直接读取数据
/// </summary>
static void GetFileStream1()
{
    string FilePath = @"E:\开发学习\流的认知\File\66619000200113962020080716543620200807085900.txt";
    FileStream sterm = new FileStream(FilePath, FileMode.OpenOrCreate, FileAccess.Read);
    byte[] byData = new byte[sterm.Length]; //建立一个FileStream要用的字节组
    sterm.Seek(0, SeekOrigin.Begin); //指定从那个字节读数据
    sterm.Read(byData, 0, byData.Length);

    #region 方法1.将字节组直接转换成utf8字符组
    //char[] charData = new char[byData.Length]; //建立一个字符组
    //Decoder d = Encoding.UTF8.GetDecoder();
    //d.GetChars(byData, 0, byData.Length, charData, 0); //将编码字节数组转换为字符数组
    #endregion

    #region 方法2.直接将字节组转换成utf8字符组
    string charData = Encoding.UTF8.GetString(byData);
    #endregion

    Console.WriteLine(charData);
    sterm.Close();
    sterm.Dispose();
}

StreamReade、StreamWriter

 /// <summary>
 /// 用StreamWriter配合FileStream写入数据
 /// </summary>
 static void GetFileStream4()
 {
     string content = @"<?xml version='1.0' encoding='utf-8'?>
<TAS>
<szUTCDate>20200807085759</szUTCDate>
<szTaDomain>POS</szTaDomain>
<szTaType>SA</szTaType>
<szTaOperationType>SALE</szTaOperationType>
<szInfo>0</szInfo>
<bNotPrinted>-1</bNotPrinted>
<lClientID>1</lClientID>
<szExternalClientID>CN</szExternalClientID>
<szClientName>CHINA</szClientName>
<szMode>POSMODE</szMode>
<szSessionID>6190:2:11343:2:20200807</szSessionID>
<szFooterLine1>HAVE A NICE DAY – 祝您购物愉快</szFooterLine1>
<szFooterLine2>美丽购物新捷径</szFooterLine2>
<szFooterLine3>退货规定</szFooterLine3>
<szFooterLine4>所有护肤,彩妆,香水产品, 一经售出,不予退换,过敏问题除外。</szFooterLine4>
<szFooterLine5>2.如使用产品过敏,请凭制定医院证明及原始购物小票办理退货,因化妆品有一定的使</szFooterLine5>
<szFooterLine6 Type='202'>3.门店不接受非本店售出商品的退换货。</szFooterLine6>
< szFooterLine7 Type = '202'> 4.商品退货时需退回相应的赠品,如赠品不能退回将酌情扣除部分退货金额。</ szFooterLine7 >
    </ TAS > ";
     string FilePath = @"E:\开发学习\流的认知\File\test.txt";
     FileStream sterm = new FileStream(FilePath, FileMode.Truncate);
     StreamWriter sw = new StreamWriter(sterm);
     sw.Write(content);
     sw.Close();
     sw.Dispose();
     sterm.Close();
     sterm.Dispose();
 }

 /// <summary>
 /// 用StreamReader配合FileStream读取数据
 /// </summary>
 static void GetFileStream3()
 {
     string FilePath = @"E:\开发学习\流的认知\File\66619000200113962020080716543620200807085900.txt";
     FileStream sterm = new FileStream(FilePath, FileMode.Open);
     StreamReader sr = new StreamReader(sterm);
     #region 直接读取所有数据
     Console.WriteLine(sr.ReadToEnd());
     #endregion

     #region 一行一行的读取
     //string read = null;
     //while ((read = sr.ReadLine()) != null)
     //{
     //    Console.WriteLine(read);
     //}
     #endregion

     sr.Close();
     sr.Dispose();
 }

MemoryStream

/// <summary>
/// 用MemoryStream1写入数据
/// </summary>
static void GetMemoryStream1() 
{
    string content = @"<?xml version='1.0' encoding='utf-8'?>
<TAS>
<szUTCDate>20200807085759</szUTCDate>
<szTaDomain>POS</szTaDomain>
<szTaType>SA</szTaType>
<szTaOperationType>SALE</szTaOperationType>
<szInfo>0</szInfo>
<bNotPrinted>-1</bNotPrinted>
<lClientID>1</lClientID>
<szExternalClientID>CN</szExternalClientID>
<szClientName>CHINA</szClientName>
<szMode>POSMODE</szMode>
<szSessionID>6190:2:11343:2:20200807</szSessionID>
<szFooterLine1>HAVE A NICE DAY – 祝您购物愉快</szFooterLine1>
<szFooterLine2>美丽购物新捷径</szFooterLine2>
<szFooterLine3>退货规定</szFooterLine3>
<szFooterLine4>所有护肤,彩妆,香水产品, 一经售出,不予退换,过敏问题除外。</szFooterLine4>
<szFooterLine5>2.如使用产品过敏,请凭制定医院证明及原始购物小票办理退货,因化妆品有一定的使</szFooterLine5>
<szFooterLine6 Type='202'>3.门店不接受非本店售出商品的退换货。</szFooterLine6>
< szFooterLine7 Type = '202'> 4.商品退货时需退回相应的赠品,如赠品不能退回将酌情扣除部分退货金额。</ szFooterLine7 >
   </ TAS > ";

    MemoryStream memory = new MemoryStream();
    byte[] array = Encoding.UTF8.GetBytes(content);//将字符串转化为字节数组
    memory.Seek(5000,SeekOrigin.Begin);
    memory.Write(array,0, array.Length);

    byte[] arrayNew = memory.ToArray();//将内存中的数据转换为字节数组
    string strNew = Encoding.UTF8.GetString(arrayNew);//将字节数组转换为字符串
    Console.WriteLine(strNew);
    memory.Close();
    memory.Dispose();

    //byte[] array = Encoding.UTF8.GetBytes(content);//将字符串转化为字节数组
    //MemoryStream memory = new MemoryStream(array);//初始化MemoryStream类

    //byte[] arrayNew = memory.ToArray();//将内存中的数据转换为字节数组
    //string strNew = Encoding.UTF8.GetString(arrayNew);//将字节数组转换为字符串
    //Console.WriteLine(strNew);
    //memory.Close();
    //memory.Dispose();
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.1 什么是Stream? 1.2 什么是字节序列? 1.3 Stream的构造函数 1.4 Stream的重要属性及方法 1.5 Stream的示例 1.6 Stream异步读写 1.7 Stream 和其子类的类图 2.1 为什么要介绍 TextReader? 2.2 TextReader的常用属性和方法 2.3 TextReader 示例 2.4 从StreamReader想到多态 2.5 简单介绍下Encoding 编码 2.6 StreamReader 的定义及作用 2.7 StreamReader 类的常用方法属性 2.8 StreamReader示例 3.1 为何介绍TextWriter? 3.2 TextWriter的构造,常用属性和方法 3.3 IFormatProvider的简单介绍 3.4 如何理解StreamWriter? 3.5 StreamWriter属性 3.6 StreamWriter示例 4.1 如何去理解FileStream? 4.2 FileStream的重要性 4.3 FileStream常用构造函数(重要) 4.4 非托管参数SafeFileHandle简单介绍 4.5 FileStream常用属性介绍 4.6 FileStream常用方法介绍 4.7 FileStream示例1:*文件的新建和拷贝(主要演示文件同步和异步操作) 4.8 FileStream示例2:*实现文件本地分段上传 5.1 简单介绍一下MemoryStream 5.2 MemoryStream和FileStream的区别 5.3 通过部分源码深入了解下MemoryStream 5.4 分析MemorySteam最常见的OutOfMemory异常 5.5 MemoryStream 的构造 5.6 MemoryStream 的属性 5.7 MemoryStream 的方法 5.8 MemoryStream 简单示例 : XmlWriter中使用MemoryStream 5.9 MemoryStream 简单示例 :自定义一个处理图片的HttpHandler 6.1 简单介绍一下BufferedStream 6.2 如何理解缓冲区? 6.3 BufferedStream的优势 6.4 从BufferedStream学习装饰模式 6.5 如何理解装饰模式 6.6 再次理解下装饰模式在Stream中的作用 6.7 BufferedStream的构造 6.8 BufferedStream的属性 6.9 BufferedStream的方法 6.10 简单示例:利用socket 读取网页并保存在本地 7.1 NetworkStream的作用 7.2 简单介绍下TCP/IP 协议和相关层次 7.3 简单说明下 TCP和UDP的区别 7.4 简单介绍下套接字(Socket)的概念 7.5 简单介绍下TcpClient,TcpListener,IPEndPoint类的作用 7.6 使用NetworkStream的注意事项和局限性 7.7 NetworkStream的构造 7.8 NetworkStream的属性 7.9 NetworkStream的方法 7.10 NetwrokStream的简单示例 7.11 创建一个客户端向服务端传输图片的小示例 版权归作者所有,仅供学习参考
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值