国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

.Net筆記:System.IO之Stream的使用詳解

2020-01-24 03:18:23
字體:
來源:轉載
供稿:網友
Stream在msdn的定義:提供字節序列的一般性視圖(provides a generic view of a sequence of bytes)。這個解釋太抽象了,不容易理解;從stream的字面意思“河,水流”更容易理解些,stream是一個抽象類,它定義了類似“水流”的事物的一些統一行為,包括這個“水流”是否可以抽水出來(讀取流內容);是否可以往這個“水流”中注水(向流中寫入內容);以及這個“水流”有多長;如何關閉“水流”,如何向“水流”中注水,如何從“水流”中抽水等“水流”共有的行為。
常用的Stream的子類有:
1) MemoryStream 存儲在內存中的字節流
2) FileStream  存儲在文件系統的字節流
3) NetworkStream 通過網絡設備讀寫的字節流
4) BufferedStream 為其他流提供緩沖的流
Stream提供了讀寫流的方法是以字節的形式從流中讀取內容。而我們經常會用到從字節流中讀取文本或者寫入文本,微軟提供了StreamReader和StreamWriter類幫我們實現在流上讀寫字符串的功能。
下面看下如何操作Stream,即如何從流中讀取字節序列,如何向流中寫字節
1. 使用Stream.Read方法從流中讀取字節,如下示例注釋:
復制代碼 代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace UseStream
{
    class Program
    {
        //示例如何從流中讀取字節流
        static void Main(string[] args)
        {
            var bytes = new byte[] {(byte)1,(byte)2,(byte)3,(byte)4,(byte)5,(byte)6,(byte)7,(byte)8};
            using (var memStream = new MemoryStream(bytes))
            {
                int offset = 0;
                int readOnce = 4;
                do
                {
                    byte[] byteTemp = new byte[readOnce];
                    // 使用Read方法從流中讀取字節
                    //第一個參數byte[]存儲從流中讀出的內容
                    //第二個參數為存儲到byte[]數組的開始索引,
                    //第三個int參數為一次最多讀取的字節數
                    //返回值是此次讀取到的字節數,此值小于等于第三個參數
                    int readCn = memStream.Read(byteTemp, 0, readOnce);
                    for (int i = 0; i < readCn; i++)
                    {
                        Console.WriteLine(byteTemp[i].ToString());
                    }

                    offset += readCn;

                    //當實際讀取到的字節數小于設定的讀取數時表示到流的末尾了
                    if (readCn < readOnce) break;
                } while (true);
            }
            Console.Read();
        }
    }
}

2. 使用Stream.BeginRead方法讀取FileStream的流內容
注意:BeginRead在一些流中的實現和Read完全相同,比如MemoryStream;而在FileStream和NetwordStream中BeginRead就是實實在在的異步操作了。
如下示例代碼和注釋:
復制代碼 代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
namespace UseBeginRead
{
    class Program
    {
        //定義異步讀取狀態類
        class AsyncState
        {
            public FileStream FS { get; set; }

            public byte[] Buffer { get; set; }

            public ManualResetEvent EvtHandle { get; set; }
        }
        static  int bufferSize = 512;
        static void Main(string[] args)
        {
            string filePath = "d://test.txt";
            //以只讀方式打開文件流
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                var buffer = new byte[bufferSize];

                //構造BeginRead需要傳遞的狀態
                var asyncState = new AsyncState { FS = fileStream, Buffer = buffer ,EvtHandle = new ManualResetEvent(false)};

                //異步讀取
                IAsyncResult asyncResult = fileStream.BeginRead(buffer, 0, bufferSize, new AsyncCallback(AsyncReadCallback), asyncState);

                //阻塞當前線程直到讀取完畢發出信號
                asyncState.EvtHandle.WaitOne();
                Console.WriteLine();
                Console.WriteLine("read complete");
                Console.Read();
            }
        }
        //異步讀取回調處理方法
        public static void AsyncReadCallback(IAsyncResult asyncResult)
        {
            var asyncState = (AsyncState)asyncResult.AsyncState;
            int readCn = asyncState.FS.EndRead(asyncResult);
            //判斷是否讀到內容
            if (readCn > 0)
            {
                byte[] buffer;
                if (readCn == bufferSize) buffer = asyncState.Buffer;
                else
                {
                    buffer = new byte[readCn];
                    Array.Copy(asyncState.Buffer, 0, buffer, 0, readCn);
                }

                //輸出讀取內容值
                string readContent = Encoding.UTF8.GetString(buffer);
                Console.Write(readContent);
            }

            if (readCn < bufferSize)
            {
                asyncState.EvtHandle.Set();
            }
            else {
                Array.Clear(asyncState.Buffer, 0, bufferSize);
                //再次執行異步讀取操作
                asyncState.FS.BeginRead(asyncState.Buffer, 0, bufferSize, new AsyncCallback(AsyncReadCallback), asyncState);
            }
        }
    }
}

3. 使用Stream.Write方法向流中寫字節數組
在使用Write方法時,需要先使用Stream的CanWrite方法判斷流是否可寫,如下示例定義了一個MemoryStream對象,然后向內存流中寫入一個字節數組
復制代碼 代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace UseStreamWrite
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var ms = new MemoryStream())
            {
                int count = 20;
                var buffer = new byte[count];
                for (int i = 0; i < count; i++)
                {
                    buffer[i] = (byte)i;
                }

                //將流當前位置設置到流的起點
                ms.Seek(0, SeekOrigin.Begin);

                Console.WriteLine("ms position is " + ms.Position);

                //注意在調用Stream的Write方法之前要用CanWrite判斷Stream是否可寫
                if (ms.CanWrite)
                {
                    ms.Write(buffer, 0, count);
                }

                //正確寫入的話,流的位置會移動到寫入開始位置加上寫入的字節數
                Console.WriteLine("ms position is " + ms.Position);
            }

            Console.Read();
        }
    }
}

4. 使用Stream.BeginWrite方法異步寫;異步寫可以提高程序性能,這是因為磁盤或者網絡IO的速度遠小于cpu的速度,異步寫可以減少cpu的等待時間。
如下使用FileStream異步寫文件的操作示例
復制代碼 代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
namespace UseStreamBeginWrite
{
    class Program
    {
        /// <summary>
        /// 異步回調需要的參數封裝類
        /// </summary>
        class AsyncState {
            public int WriteCountOnce { get; set; }
            public int Offset { get; set; }
            public byte[] Buffer { get; set; }
            public ManualResetEvent WaitHandle { get; set; }
            public FileStream FS { get; set; }
        }
        static void Main(string[] args)
        {
            //準備一個1K的字節數組
            byte[] toWriteBytes = new byte[1 << 10];
            for (int i = 0; i < toWriteBytes.Length; i++)
            {
                toWriteBytes[i] = (byte)(i % byte.MaxValue);
            }
            string filePath = "d://test.txt";
            //FileStream實例
            using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
            {
                int offset = 0;
                //每次寫入32字節
                int writeCountOnce = 1 << 5;
                //構造回調函數需要的狀態
                AsyncState state = new AsyncState{
                    WriteCountOnce = writeCountOnce,
                    Offset = offset,
                    Buffer = toWriteBytes,
                    WaitHandle = new ManualResetEvent(false),
                    FS = fileStream
                };

                //做異步寫操作
                fileStream.BeginWrite(toWriteBytes, offset, writeCountOnce, WriteCallback, state);

                //等待寫完畢或者出錯發出的繼續信號
                state.WaitHandle.WaitOne();
            }
            Console.WriteLine("Done");
            Console.Read();
        }
        /// <summary>
        /// 異步寫的回調函數
        /// </summary>
        /// <param name="asyncResult">寫狀態</param>
        static void WriteCallback(IAsyncResult asyncResult)
        {
            AsyncState state = (AsyncState)asyncResult.AsyncState;

            try
            {
                state.FS.EndWrite(asyncResult);
            }
            catch (Exception ex)
            {
                Console.WriteLine("EndWrite Error:" + ex.Message);
                state.WaitHandle.Set();
                return;
            }

            Console.WriteLine("write to " + state.FS.Position);
            //判斷是否寫完,未寫完繼續異步寫
            if (state.Offset + state.WriteCountOnce < state.Buffer.Length)
            {
                state.Offset += state.WriteCountOnce;
                Console.WriteLine("call BeginWrite again");
                state.FS.BeginWrite(state.Buffer, state.Offset, state.WriteCountOnce, WriteCallback, state);
            }
            else {
                //寫完發出完成信號
                state.WaitHandle.Set();
            }
        }
    }
}

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 杨浦区| 寻乌县| 津南区| 兴业县| 平顺县| 右玉县| 辉县市| 日喀则市| 周口市| 石阡县| 湄潭县| 阜新| 吴旗县| 察隅县| 扶沟县| 浠水县| 梅州市| 苍山县| 常德市| 随州市| 太湖县| 潞西市| 汶上县| 昂仁县| 长泰县| 余干县| 叙永县| 河西区| 广平县| 屯留县| 迁西县| 永年县| 江口县| 莱阳市| 方山县| 辉县市| 石门县| 天门市| 新田县| 嘉兴市| 东阿县|