<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      C# 溫故而知新:Stream篇 (四)

      C# 溫故而知新:Stream篇(四)

      FileStream

      目錄:

       

       

       

       

            

      如何去理解FileStream?

      通過前3章的學習相信大家對于Stream已經(jīng)有一定的了解,但是又如何去理解FileStream呢?請看下圖  

      我們磁盤的中任何文件都是通過2進制組成,最為直觀的便是記事本了,當我們新建一個記事本時,它的大小是0KB, 我們每次輸入一個數(shù)字或

      字母時文件便會自動增大4kb,可見隨著我們輸入的內(nèi)容越來越多,文件也會相應增大,同理當我們刪除文件內(nèi)容時,文件也會相應減小,對了,

      聰明的你肯定會問:誰將內(nèi)容以怎么樣的形式放到文件中去了?好問題,還記得第一篇流的概念么?對了,真實世界的一群魚可以通過河流來

      往于各個地方,F(xiàn)ileStream也是一樣,byte可以通過FileStream進行傳輸,這樣我們便能在計算機上對任何文件進行一系列的操作了。

       

       

      FileStream 的重要性

      FileStream 顧名思義文件流,我們電腦上的文件都可以通過文件流進行操作,例如文件的復制,剪切,粘貼,刪除, 本地文件上傳,下載,等許

      多重要的功能都離不開文件流,所以文件流不僅在本機上非常重要,在如今的網(wǎng)絡世界也是萬萬不能缺少的,想象一下我們開啟虛機后,直接從本

      地復制一個文件到虛機上,是多么方便,如果沒有文件流,這個將難以想象。(大家別誤解,文件流無法直接通過網(wǎng)絡進行傳輸,而是

      通過網(wǎng)絡流將客戶端上傳的文件傳到服務器端接收,然后通過文件流進行處理,下載正好相反)

       

      FileStream 常用構造函數(shù)介紹可能理解上有點復雜,請大家務必深刻理解

       *1: FileStream(SafeFileHandle, FileAccess)

                     非托管參數(shù)SafeFileHandle簡單介紹

                                 SafeFileHandle :是一個文件安全句柄,這樣的解釋可能大家一頭霧水,

        別急,大家先不要去理睬這深邃的含義,只要知道這個類型是c#非托管資源

        也就是說它能夠調(diào)用非托管資源的方法,而且不屬于c#回收機制,所以我們必須

        使用GC手動或其他方式(Finalize 或Dispose方法)進行非托管資源的回收,所以

        SafeFileHandle是個默默無聞的保鏢 ,一直暗中保護FileStream和文件的安全

        為了能讓大家更好的理解這個保鏢,請看第一段代碼:

                                會什么會報錯呢?其實程序被卡在 Console.ReadLine()這里,F(xiàn)ileStream并沒有

        被釋放,系統(tǒng)不知道這個文件是否還有用﹐所以幫我們保護這個文件

        (那個非托管資源SafeFileHandle所使用的內(nèi)存還被程序占用著)

        所以SafeFileHandled 在內(nèi)部保護了這個文件從而報出了這個異常

        如果我們將流關閉后,這個問題也就不存在了

      可以看見stream.SafeFileHandle的IsClose屬性變成true了,也就是說這時候可以安全的刪除文件了 

      所以又回到了一個老問題上面,我們每次使用完FileStream后都必須將他關閉并釋放資源

      *2: FileStream(String, FileMode)

      String 參數(shù)表示文件所在的地址,FIleMode是個枚舉,表示確定如何打開或創(chuàng)建文件。

      FileMode枚舉參數(shù)包含以下內(nèi)容:

      成員名稱

      說明

      Append

      打開現(xiàn)有文件并查找到文件尾,或創(chuàng)建新文件。FileMode.Append 只能同 FileAccess.Write 一起使用。

          

      Create

      指定操作系統(tǒng)應創(chuàng)建新文件。如果文件已存在,它將被改寫。這要求 FileIOPermissionAccess.Write。

      System.IO.FileMode.Create 等效于這樣的請求:如果文件不存在,則使用 CreateNew;否則使用 Truncate。

      CreateNew

      指定操作系統(tǒng)應創(chuàng)建新文件。此操作需要 FileIOPermissionAccess.Write。如果文件已存在,則將引發(fā) IOException

          

      Open

      指定操作系統(tǒng)應打開現(xiàn)有文件。打開文件的能力取決于 FileAccess   所指定的值。如果該文件不存在,

      則引發(fā) System.IO.FileNotFoundException。

          

      OpenOrCreate

      指定操作系統(tǒng)應打開文件(如果文件存在);否則,應創(chuàng)建新文件。如果用 FileAccess.Read   打開文件,則需要

       FileIOPermissionAccess.Read。如果文件訪問為 FileAccess.Write 或 FileAccess.ReadWrite,則需要

      FileIOPermissionAccess.Write。如果文件訪問為 FileAccess.Append,則需要 FileIOPermissionAccess.Append。

          

      Truncate

      指定操作系統(tǒng)應打開現(xiàn)有文件。文件一旦打開,就將被截斷為零字節(jié)大小。此操作需要 FileIOPermissionAccess.Write。

      試圖從使用 Truncate 打開的文件中進行讀取將導致異常。

      *3: FileStream(IntPtr, FileAccess, Boolean ownsHandle)

             FileAccess 參數(shù)也是一個枚舉, 表示對于該文件的操作權限

      ReadWrite

      對文件的讀訪問和寫訪問。可從文件讀取數(shù)據(jù)和將數(shù)據(jù)寫入文件

      Write

      文件的寫訪問。可將數(shù)據(jù)寫入文件。同 Read組合即構成讀/寫訪問權

      Read

      對文件的讀訪問。可從文件中讀取數(shù)據(jù)。同 Write組合即構成讀寫訪問權

      參數(shù)ownsHandle:也就是類似于前面和大家介紹的SafeFileHandler,有2點必須注意

            1對于指定的文件句柄,操作系統(tǒng)不允許所請求的 access,例如,當 access 為 Write 或 ReadWrite 而文件句柄設置為只讀訪問時,會報出異常。

             所以 ownsHandle才是老大,FileAccess的權限應該在ownsHandle的范圍之內(nèi)

                  2. FileStream 假定它對句柄有獨占控制權。當 FileStream 也持有句柄時,讀取、寫入或查找可能會導致數(shù)據(jù)破壞為了數(shù)據(jù)的安全,請使用

                  句柄調(diào)用 Flush,并避免在使用完句柄后調(diào)用 Close 以外的任何方法。

       

      *4: FileStream(String, FileMode, FileAccess, FileShare)

      FileShare:同樣是個枚舉類型:確定文件如何由進程共。   

      Delete

      允許隨后刪除文件。

      Inheritable

      使文件句柄可由子進程繼承。Win32 不直接支持此功能。

      None

      謝絕共享當前文件。文件關閉前,打開該文件的任何請求(由此進程或另一進程發(fā)出的請求)都將失敗。

      Read

      允許隨后打開文件讀取。如果未指定此標志則文件關閉前,任何打開該文件以進行讀取的請求(由此進程或另一進程發(fā)出的請求)都將失敗。但是,即使指定了此標志,仍可能需要附加權限才能夠訪問該文件。

      ReadWrite

      允許隨后打開文件讀取或寫入。如果未指定此標志,則文件關閉前,任何打開該文件以進行讀取或寫入的請求(由此進程或另一進程發(fā)出)都將失敗。但是,即使指定了此標志,仍可能需要附加權限才能夠訪問該文件。

      Write

      允許隨后打開文件寫入。如果未指定此標志,則文件關閉前,任何打開該文件以進行寫入的請求(由此進程或另一進過程發(fā)出的請求)都將失敗。但是,即使指定了此標志,仍可能需要附加權限才能夠訪問該文件。

      *5: FileStream(String, FileMode, FileAccess, FileShare, Int32, Boolean async )

       Int32:這是一個緩沖區(qū)的大小,大家可以按照自己的需要定制,

       Boolean async:是否異步讀寫,告訴FileStream示例,是否采用異步讀寫

       

      *6: FileStream(String, FileMode, FileAccess, FileShare, Int32, FileOptions)

            FileOptions這是類似于FileStream對于文件操作的高級選項

       

      FileStream 常用屬性介紹

       *1:CanRead :指示FileStream是否可以讀操作

       *2:CanSeek:指示FileStream是否可以跟蹤查找流操作

       *3:IsAsync:FileStream是否同步工作還是異步工作

       *4:Name:FileStream的名字 只讀屬性

       *5:ReadTimeout :設置讀取超時時間

       *6:SafeFileHandle : 文件安全句柄 只讀屬性

       *7:position:當前FileStream所在的流位置

       

      FileStream 常用方法介紹

      以下方法重寫了Stream的一些虛方法(**這里大家點擊這里可以參考第一篇來溫故下,這里不再敘述)

      1:IAsyncResult BeginRead  異步讀取

      2:IAsyncResult BeginWrite  異步寫

      3:void  Close  關閉當前FileStream

      4:void EndRead 異步讀結束

      5:void  EndWrite 異步寫結束

      6:void Flush 立刻釋放緩沖區(qū),將數(shù)據(jù)全部導出到基礎流(文件中)

      7:int Read 一般讀取

      8:int ReadByte 讀取單個字節(jié)

      9:long Seek 跟蹤查找流所在的位置

      10:void SetLength 設置FileStream的長度

      11:void Write 一般寫

      12:void  WriteByte寫入單個字節(jié)

      屬于FileStream獨有的方法

      *1:FileSecurity  GetAccessControl()

       這個不是很常用,F(xiàn)ileSecurity 是文件安全類,直接表達當前文件的訪問控制列表(ACL)的符合當前文件權限的項目,ACL大家有個了解就行,以后會單獨和大家討論下ACL方面的知識

      *2:  void Lock(long position,long length)

       這個Lock方法和線程中的Look關鍵字很不一樣,它能夠鎖住文件中的某一部分,非常的強悍!用了這個方法我們能夠精確鎖定住我們需要鎖住的文件的部分內(nèi)容

      *3:  void SetAccessControl(FileSecurity fileSecurity)

      和GetAccessControl很相似,ACL技術會在以后單獨介紹

      *4:  void Unlock (long position,long length)

      正好和lock方法相反,對于文件部分的解鎖

       

      文件的新建和拷貝(主要演示文件同步和異步操作)

                  首先我們嘗試DIY一個IFileConfig

          /// <summary>
      /// 文件配置接口
      /// </summary>
      public interface IFileConfig
      {
      string FileName { get; set; }
      bool IsAsync { get; set; }
      }

      創(chuàng)建文件配置類CreateFileConfig,用于添加文件一些配置設置,實現(xiàn)添加文件的操作

          /// <summary>
      /// 創(chuàng)建文件配置類
      /// </summary>
      public class CreateFileConfig : IFileConfig
      {
      // 文件名
      public string FileName { get; set; }
      //是否異步操作
      public bool IsAsync { get; set; }
      //創(chuàng)建文件所在url
      public string CreateUrl { get; set; }
      }

      讓我們定義一個文件流測試類:FileStreamTest 來實現(xiàn)文件的操作

          /// <summary>
      /// FileStreamTest 類
      /// </summary>
      public class FileStreamTest

      在該類中實現(xiàn)一個簡單的Create方法用來同步或異步的實現(xiàn)添加文件,F(xiàn)ileStream會根據(jù)配置類去選擇相應的構造函數(shù),實現(xiàn)異步或同步的添加方式

             /// <summary>
      /// 添加文件方法
      /// </summary>
      /// <param name="config"> 創(chuàng)建文件配置類</param>
      public void Create(IFileConfig config)
      {
      lock (_lockObject)
      {
      //得到創(chuàng)建文件配置類對象
      var createFileConfig = config as CreateFileConfig;
      //檢查創(chuàng)建文件配置類是否為空
      if (this.CheckConfigIsError(config)) return;
      //假設創(chuàng)建完文件后寫入一段話,實際項目中無需這么做,這里只是一個演示
      char[] insertContent = "HellowWorld".ToCharArray();
      //轉化成 byte[]
      byte[] byteArrayContent = Encoding.Default.GetBytes(insertContent, 0, insertContent.Length);
      //根據(jù)傳入的配置文件中來決定是否同步或異步實例化stream對象
      FileStream stream = createFileConfig.IsAsync ?
      new FileStream(createFileConfig.CreateUrl, FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, true)
      : new FileStream(createFileConfig.CreateUrl, FileMode.Create);
      using (stream)
      {
      // 如果不注釋下面代碼會拋出異常,google上提示是WriteTimeout只支持網(wǎng)絡流
      // stream.WriteTimeout = READ_OR_WRITE_TIMEOUT;
      //如果該流是同步流并且可寫
      if (!stream.IsAsync && stream.CanWrite)
      stream.Write(byteArrayContent, 0, byteArrayContent.Length);
      else if (stream.CanWrite)//異步流并且可寫
      stream.BeginWrite(byteArrayContent, 0, byteArrayContent.Length, this.End_CreateFileCallBack, stream);

      stream.Close();
      }
      }
      }

      如果采用異步的方式則最后會進入End_CreateFileCallBack回調(diào)方法,result.AsyncState對象就是上圖stream.BeginWrite()方法的最后一個參數(shù)

      還有一點必須注意的是每一次使用BeginWrite()方法事都要帶上EndWrite()方法,Read方法也一樣

              /// <summary>
      /// 異步寫文件callBack方法
      /// </summary>
      /// <param name="result">IAsyncResult</param>
      private void End_CreateFileCallBack(IAsyncResult result)
      {
      //從IAsyncResult對象中得到原來的FileStream
      var stream = result.AsyncState as FileStream;
      //結束異步寫

      Console.WriteLine("異步創(chuàng)建文件地址:{0}", stream.Name);
      stream.EndWrite(result);
      Console.ReadLine();
      }

      文件復制的方式思路比較相似,首先定義復制文件配置類,由于在異步回調(diào)中用到該配置類的屬性,所以新增了文件流對象和相應的字節(jié)數(shù)組

          /// <summary>
      /// 文件復制
      /// </summary>
      public class CopyFileConfig : IFileConfig
      {
      // 文件名
      public string FileName { get; set; }
      //是否異步操作
      public bool IsAsync { get; set; }
      //原文件地址
      public string OrginalFileUrl { get; set; }
      //拷貝目的地址
      public string DestinationFileUrl { get; set; }
      //文件流,異步讀取后在回調(diào)方法內(nèi)使用
      public FileStream OriginalFileStream { get; set; }
      //原文件字節(jié)數(shù)組,異步讀取后在回調(diào)方法內(nèi)使用
      public byte[] OriginalFileBytes { get; set; }
      }

      然后在FileStreamTest 類中新增一個Copy方法實現(xiàn)文件的復制功能

              /// <summary>
      /// 復制方法
      /// </summary>
      /// <param name="config">拷貝文件復制</param>
      public void Copy(IFileConfig config)
      {
      lock (_lockObject)
      {
      //得到CopyFileConfig對象
      var copyFileConfig = config as CopyFileConfig;
      // 檢查CopyFileConfig類對象是否為空或者OrginalFileUrl是否為空
      if (CheckConfigIsError(copyFileConfig) || !File.Exists(copyFileConfig.OrginalFileUrl)) return;
      //創(chuàng)建同步或異步流
      FileStream stream = copyFileConfig.IsAsync ?
      new FileStream(copyFileConfig.OrginalFileUrl, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true)
      : new FileStream(copyFileConfig.OrginalFileUrl, FileMode.Open);
      //定義一個byte數(shù)組接受從原文件讀出的byte數(shù)據(jù)
      byte[] orignalFileBytes = new byte[stream.Length];
      using (stream)
      {
      // stream.ReadTimeout = READ_OR_WRITE_TIMEOUT;
      //如果異步流
      if (stream.IsAsync)
      {
      //將該流和讀出的byte[]數(shù)據(jù)放入配置類,在callBack中可以使用
      copyFileConfig.OriginalFileStream = stream;
      copyFileConfig.OriginalFileBytes = orignalFileBytes;
      if (stream.CanRead)
      //異步開始讀取,讀完后進入End_ReadFileCallBack方法,該方法接受copyFileConfig參數(shù)
      stream.BeginRead(orignalFileBytes, 0, orignalFileBytes.Length, End_ReadFileCallBack, copyFileConfig);
      }
      else//否則同步讀取
      {
      if (stream.CanRead)
      {
      //一般讀取原文件
      stream.Read(orignalFileBytes, 0, orignalFileBytes.Length);
      }
      //定義一個寫流,在新位置中創(chuàng)建一個文件
      FileStream copyStream = new FileStream(copyFileConfig.DestinationFileUrl, FileMode.CreateNew);
      using (copyStream)
      {
      // copyStream.WriteTimeout = READ_OR_WRITE_TIMEOUT;
      //將源文件的內(nèi)容寫進新文件
      copyStream.Write(orignalFileBytes, 0, orignalFileBytes.Length);
      copyStream.Close();
      }
      }
      stream.Close();
      Console.ReadLine();
      }
      }


      }

      最后,如果采用異步的方式,則會進入End_ReadFileCallBack回調(diào)函數(shù)進行異步讀取和異步寫操作

        /// <summary>
      /// 異步讀寫文件方法
      /// </summary>
      /// <param name="result"></param>
      private void End_ReadFileCallBack(IAsyncResult result)
      {
      //得到先前的配置文件
      var config = result.AsyncState as CopyFileConfig;
      //結束異步讀
      config.OriginalFileStream.EndRead(result);
      //異步讀后立即寫入新文件地址
      if (File.Exists(config.DestinationFileUrl)) File.Delete(config.DestinationFileUrl);
      FileStream copyStream = new FileStream(config.DestinationFileUrl, FileMode.CreateNew);
      using (copyStream)
      {
      Console.WriteLine("異步復制原文件地址:{0}", config.OriginalFileStream.Name);
      Console.WriteLine("復制后的新文件地址:{0}", config.DestinationFileUrl);
      //調(diào)用異步寫方法CallBack方法為End_CreateFileCallBack,參數(shù)是copyStream
      copyStream.BeginWrite(config.OriginalFileBytes, 0, config.OriginalFileBytes.Length, this.End_CreateFileCallBack,copyStream);
      copyStream.Close();

      }

      }

       

      最后讓我們在main函數(shù)調(diào)用下:

        static void Main(string[] args)
      {
      FileStreamTest test = new FileStreamTest();
      //創(chuàng)建文件配置類
      CreateFileConfig createFileConfig = new CreateFileConfig { CreateUrl = @"d:\MyFile.txt", IsAsync = true };
      //復制文件配置類
      CopyFileConfig copyFileConfig = new CopyFileConfig
      {
      OrginalFileUrl = @"d:\8.jpg",
      DestinationFileUrl = @"d:\9.jpg",
      IsAsync = true
      };
      test.Create(createFileConfig);
      test.Copy(copyFileConfig);
      }

      輸出結果:

       

      實現(xiàn)文件本地分段上傳

                  上面的例子是將一個文件作為整體進行操作,這樣會帶來一個問題,當文件很大或者網(wǎng)絡不是很穩(wěn)定的時候會發(fā)生意想不到的錯誤

                   那我們該怎么解決這一問題呢?其實有種思路還是不錯的,那就是分段傳輸:

                    

      那就DIY一個簡單的分段傳輸?shù)睦樱覀兿葘⑻幚砻恳欢蔚倪壿嬒日砗?/p>

      /// <summary>
      /// 分段上傳例子
      /// </summary>
      public class UpFileSingleTest
      {
      //我們定義Buffer為1000
      public const int BUFFER_COUNT = 1000;

      /// <summary>
      /// 將文件上傳至服務器(本地),由于采取分段傳輸所以,
      /// 每段必須有一個起始位置和相對應該數(shù)據(jù)段的數(shù)據(jù)
      /// </summary>
      /// <param name="filePath">服務器上文件地址</param>
      /// <param name="startPositon">分段起始位置</param>
      /// <param name="btArray">每段的數(shù)據(jù)</param>
      private void WriteToServer(string filePath,int startPositon,byte[] btArray)
      {
      FileStream fileStream = new FileStream(filePath, FileMode.OpenOrCreate);
      using (fileStream)
      {
      //將流的位置設置在該段起始位置
      fileStream.Position = startPositon;
      //將該段數(shù)據(jù)通過FileStream寫入文件中,每次寫一段的數(shù)據(jù),就好比是個水池,分段蓄水一樣,直到蓄滿為止
      fileStream.Write(btArray, 0, btArray.Length);
      }
      }


      /// <summary>
      /// 處理單獨一段本地數(shù)據(jù)上傳至服務器的邏輯,根據(jù)客戶端傳入的startPostion
      /// 和totalCount來處理相應段的數(shù)據(jù)上傳至服務器(本地)
      /// </summary>
      /// <param name="localFilePath">本地需要上傳的文件地址</param>
      /// <param name="uploadFilePath">服務器(本地)目標地址</param>
      /// <param name="startPostion">該段起始位置</param>
      /// <param name="totalCount">該段最大數(shù)據(jù)量</param>
      public void UpLoadFileFromLocal(string localFilePath,string uploadFilePath,int startPostion,int totalCount)
      {
      //if(!File.Exists(localFilePath)){return;}
      //每次臨時讀取數(shù)據(jù)數(shù)
      int tempReadCount = 0;
      int tempBuffer = 0;
      //定義一個緩沖區(qū)數(shù)組
      byte[] bufferByteArray = new byte[BUFFER_COUNT];
      //定義一個FileStream對象
      FileStream fileStream = new FileStream(localFilePath,FileMode.Open);
      //將流的位置設置在每段數(shù)據(jù)的初始位置
      fileStream.Position = startPostion;
      using (fileStream)
      {
      //循環(huán)將該段數(shù)據(jù)讀出在寫入服務器中
      while (tempReadCount < totalCount)
      {

      tempBuffer = BUFFER_COUNT;
      //每段起始位置+每次循環(huán)讀取數(shù)據(jù)的長度
      var writeStartPosition = startPostion + tempReadCount;
      //當緩沖區(qū)的數(shù)據(jù)加上臨時讀取數(shù)大于該段數(shù)據(jù)量時,
      //則設置緩沖區(qū)的數(shù)據(jù)為totalCount-tempReadCount 這一段的數(shù)據(jù)
      if (tempBuffer + tempReadCount > totalCount)
      {
      //緩沖區(qū)的數(shù)據(jù)為totalCount-tempReadCount
      tempBuffer = totalCount-tempReadCount;
      //讀取該段數(shù)據(jù)放入bufferByteArray數(shù)組中
      fileStream.Read(bufferByteArray, 0, tempBuffer);
      if (tempBuffer > 0)
      {
      byte[] newTempBtArray = new byte[tempBuffer];
      Array.Copy(bufferByteArray, 0, newTempBtArray, 0, tempBuffer);
      //將緩沖區(qū)的數(shù)據(jù)上傳至服務器
      this.WriteToServer(uploadFilePath, writeStartPosition, newTempBtArray);
      }

      }
      //如果緩沖區(qū)的數(shù)據(jù)量小于該段數(shù)據(jù)量,并且tempBuffer=設定BUFFER_COUNT時,通過
      //while 循環(huán)每次讀取一樣的buffer值的數(shù)據(jù)寫入服務器中,直到將該段數(shù)據(jù)全部處理完畢
      else if (tempBuffer == BUFFER_COUNT)
      {
      fileStream.Read(bufferByteArray, 0, tempBuffer);
      this.WriteToServer(uploadFilePath, writeStartPosition, bufferByteArray);
      }

      //通過每次的緩沖區(qū)數(shù)據(jù),累計增加臨時讀取數(shù)
      tempReadCount += tempBuffer;
      }
      }
      }

      }

      一切準備就緒,我們剩下的就是將文件切成幾段進行上傳了

       static void Main(string[] args)
      {
      UpFileSingleTest test=new UpFileSingleTest();
      FileInfo info = new FileInfo(@"G:\\Skyrim\20080204173728108.torrent");
      //取得文件總長度
      var fileLegth = info.Length;
      //假設將文件切成5段
      var divide = 5;
      //取到每個文件段的長度
      var perFileLengh = (int)fileLegth / divide;
      //表示最后剩下的文件段長度比perFileLengh小
      var restCount = (int)fileLegth % divide;
      //循環(huán)上傳數(shù)據(jù)
      for (int i = 0; i < divide+1; i++)
      {
      //每次定義不同的數(shù)據(jù)段,假設數(shù)據(jù)長度是500,那么每段的開始位置都是i*perFileLength
      var startPosition = i * perFileLengh;
      //取得每次數(shù)據(jù)段的數(shù)據(jù)量
      var totalCount = fileLegth - perFileLengh * i > perFileLengh ? perFileLengh : (int)(fileLegth - perFileLengh * i);
      //上傳該段數(shù)據(jù)
      test.UpLoadFileFromLocal(@"G:\\Skyrim\\20080204173728108.torrent", @"G:\\Skyrim\\20080204173728109.torrent", startPosition, i == divide ? divide : totalCount);
      }

      }

      上傳結果:

      總的來說,分段傳輸比直接傳輸復雜許多,我會在今后的例子中加入多線程,這樣的話每段數(shù)據(jù)的傳輸都能通過一個線程單獨處理,能夠提升上傳性能和速度

       

       

         本章總結

                  本章介紹了Stream中最關鍵的派生類FileStream的概念,屬性,方法,構造函數(shù)等重要的概念,包括一些難點和重要點都一一列舉出來,最后2個例子讓大家在溫故下

      FileStream的使用方法,包括FileStream異步同步操作和分段傳輸操作

                  如果大家喜歡我的文章,請大家多多關注下,下一章將會介紹MemoryStream,敬請期待!

       

       

       

       

      posted @ 2012-04-03 05:28  逆時針の風  閱讀(24416)  評論(38)    收藏  舉報
      主站蜘蛛池模板: 色欲狠狠躁天天躁无码中文字幕| 久久国产精品伊人青青草| 99精品人妻少妇一区| 国产中文99视频在线观看| 激情亚洲专区一区二区三区| 99精品国产兔费观看久久99 | 精品91在线| 久久久久无码国产精品一区| 亚洲第一福利网站在线观看| 日本高清中文字幕免费一区二区 | 精品蜜臀国产av一区二区| 久久大香萑太香蕉av黄软件| 乱老年女人伦免费视频| 久久精品国产99久久6| 91网站在线看| 亚洲高潮喷水无码AV电影| 国精品无码人妻一区二区三区 | 日本一卡2卡3卡四卡精品网站| 少女韩国在线观看完整版免费| 91精品乱码一区二区三区| 一本加勒比hezyo无码人妻| 99久久国产福利自产拍| 国产精品户外野外| 日本高清视频网站www| 色道久久综合亚洲精品蜜桃| 成人AV专区精品无码国产| 久久人人97超碰人人澡爱香蕉| 我国产码在线观看av哈哈哈网站| 国产人妻精品无码av在线| 激情国产一区二区三区四区| 国产精品国产三级国快看| 狠狠爱俺也去去就色| 猫咪AV成人永久网站在线观看| 香蕉eeww99国产在线观看| 熟女一区二区中文在线| 好男人官网资源在线观看| 少妇愉情理伦片丰满丰满午夜| 成人亚洲狠狠一二三四区| 太深太粗太爽太猛了视频| 国产精品成人av电影不卡| 黑人欧美一级在线视频|