zoukankan      html  css  js  c++  java
  • Stream篇(1)

    最近在看一个写的很好的博客,为了加深记忆,把自认为重要的东西,一边看,一边记在这里

    博客地址:http://www.cnblogs.com/JimmyZheng/archive/2012/03/17/2402814.html

    一、什么是流、字节序列、字节

    一条河中有一条鱼游过,这条鱼就是一个字节,这个字节包括眼睛、嘴巴等8组成8个二进制的位,而这条河就是流。

    字节按照一定的顺序进行排序组成了字节序列。

    二、Stream

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

    Stream stream=new Stream();

    重要的属性:

    1、CanRead:只读,判断该流是否能够读取

    2、CanSeek:只读,判断该流是否支持跟踪查找

    3、CanWrite:只读,判断该流是否可写

    4、Length:流的长度

    5、Position:非常重要,在文件或图片上传中,可能会遇到这样的事:Stream对象被缓存了,导致了Position属性在流中无法找到正确的位置。一种方法是每次使用流前将该属性设置为0.但如果想从根本解决这个问题,最好的方法是用Using语句将流对象包裹起来,用完后关闭回收即可。

    重要方法:

    1、void Flush():

    使用流写文件时,数据会先进入到缓冲区中,而不会立刻写入文件。当执行这个方法后,缓冲区的数据流会立刻注入基础流。

    2、abstract int Read(byte[] buffer, int offset,int count)

    缓冲字节数组,位偏移量,读取的字节个数

    返回一个缓冲区中的总字节数,int类型。

    3、abstract long Seek(long offset,SeekOrigin origin)

    定位流中的一个位置

    SeekOrigin.Begin/Current/End

    offset可为负0正

    4、abstract int Write(byte[] buffer, int offset,int count)

    5、virtual void Close()

    如果不用using,那记得使用这个方法

    三、例子

    非原创,呵呵

     1 static void Main(string[] args)
     2         {
     3             byte[] buffer = null;
     4 
     5             string testString = "Stream!Hello world";
     6             char[] readCharArray = null;
     7             byte[] readBuffer = null;
     8             string readString = string.Empty;
     9             //关于MemoryStream 我会在后续章节详细阐述
    10             using (MemoryStream stream = new MemoryStream()) 
    11             {
    12                 Console.WriteLine("初始字符串为:{0}", testString);
    13                 //如果该流可写
    14                 if (stream.CanWrite)
    15                 {
    16                     //首先我们尝试将testString写入流中
    17                     //关于Encoding我会在另一篇文章中详细说明,暂且通过它实现string->byte[]的转换
    18                     buffer = Encoding.Default.GetBytes(testString);
    19                     //我们从该数组的第一个位置开始写,长度为3,写完之后 stream中便有了数据
    20                     //对于新手来说很难理解的就是数据是什么时候写入到流中,在冗长的项目代码面前,我碰见过很
    21                     //多新手都会有这种经历,我希望能够用如此简单的代码让新手或者老手们在温故下基础
    22                     stream.Write(buffer, 0,3);
    23 
    24                     Console.WriteLine("现在Stream.Postion在第{0}位置",stream.Position+1);
    25 
    26                     //从刚才结束的位置(当前位置)往后移3位,到第7位
    27                     long newPositionInStream =stream.CanSeek? stream.Seek(3, SeekOrigin.Current):0;
    28 
    29                     Console.WriteLine("重新定位后Stream.Postion在第{0}位置", newPositionInStream+1);
    30                     if (newPositionInStream < buffer.Length)
    31                     {
    32                         //将从新位置(第7位)一直写到buffer的末尾,注意下stream已经写入了3个数据“Str”
    33                         stream.Write(buffer, (int)newPositionInStream, buffer.Length - (int)newPositionInStream);
    34                     }
    35 
    36                     
    37                     //写完后将stream的Position属性设置成0,开始读流中的数据
    38                     stream.Position = 0;
    39 
    40                     // 设置一个空的盒子来接收流中的数据,长度根据stream的长度来决定
    41                     readBuffer = new byte[stream.Length];
    42 
    43 
    44                     //设置stream总的读取数量 ,
    45                     //注意!这时候流已经把数据读到了readBuffer中
    46                     int count = stream.CanRead?stream.Read(readBuffer, 0, readBuffer.Length):0;
    47          
    48 
    49                     //由于刚开始时我们使用加密Encoding的方式,所以我们必须解密将readBuffer转化成Char数组,这样才能重新拼接成string
    50 
    51                     //首先通过流读出的readBuffer的数据求出从相应Char的数量
    52                     int charCount = Encoding.Default.GetCharCount(readBuffer, 0, count);
    53                     //通过该Char的数量 设定一个新的readCharArray数组
    54                     readCharArray = new char[charCount];
    55                     //Encoding 类的强悍之处就是不仅包含加密的方法,甚至将解密者都能创建出来(GetDecoder()),
    56                     //解密者便会将readCharArray填充(通过GetChars方法,把readBuffer 逐个转化将byte转化成char,并且按一致顺序填充到readCharArray中)
    57                     Encoding.Default.GetDecoder().GetChars(readBuffer, 0, count, readCharArray, 0);
    58                     for (int i = 0; i < readCharArray.Length; i++)
    59                     {
    60                         readString += readCharArray[i];
    61                     }
    62                     Console.WriteLine("读取的字符串为:{0}", readString);
    63                 }
    64 
    65                 stream.Close();
    66             }
    67 
    68             Console.ReadLine();
    69 
    70         }

    四、实现异步

    几个关键方法:

    异步读取
    public virtual IAsyncResult BeginRead(byte[] buffer,int offset,int count,AsyncCallback callback,Object state)
    异步写
    public virtual IAsyncResult BeginWrite( byte[] buffer, int offset, int count, AsyncCallback callback, Object state )
    结束异步读取
    public virtual int EndRead( IAsyncResult asyncResult ) 
    结束异步写
    public virtual void EndWrite( IAsyncResult asyncResult )

    在复杂的情况下,避免类似于阻塞问题的出现。
    感谢该博主的辛勤劳动,受益匪浅了。

  • 相关阅读:
    Python中所有的关键字
    关于selenium的8种元素定位
    对提示框的操作
    selenium+webservice进行百度登录
    MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled...报错解决
    Vue中使用echarts
    npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142解决方法
    插入排序
    冒泡排序优化
    roject 'org.springframework.boot:spring-boot-starter-parent:XXX' not found 解决
  • 原文地址:https://www.cnblogs.com/xyang/p/2487457.html
Copyright © 2011-2022 走看看