自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

淺談.NET Framework中的Stream.Read方法

開(kāi)發(fā) 后端
本文將為大家介紹Microsoft .NET Framework Base Class Library 中的 Stream.Read 方法。包括語(yǔ)法、參數(shù)等各項(xiàng)內(nèi)容。

Stream.Read 方法

當(dāng)在派生類(lèi)中重寫(xiě)時(shí),從當(dāng)前流讀取字節(jié)序列,并將此流中的位置提升讀取的字節(jié)數(shù)。

語(yǔ)法:

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

參數(shù):

buffer: 字節(jié)數(shù)組。此方法返回時(shí),該緩沖區(qū)包含指定的字符數(shù)組,該數(shù)組的 offset 和 (offset + count -1) 之間的值由從當(dāng)前源中讀取的字節(jié)替換。
offset: buffer 中的從零開(kāi)始的字節(jié)偏移量,從此處開(kāi)始存儲(chǔ)從當(dāng)前流中讀取的數(shù)據(jù)。
count: 要從當(dāng)前流中最多讀取的字節(jié)數(shù)。
返回值:

讀入緩沖區(qū)中的總字節(jié)數(shù)。如果當(dāng)前可用的字節(jié)數(shù)沒(méi)有請(qǐng)求的字節(jié)數(shù)那么多,則總字節(jié)數(shù)可能小于請(qǐng)求的字節(jié)數(shù),或者如果已到達(dá)流的末尾,則為零 (0)。

備注:

此方法的實(shí)現(xiàn)從當(dāng)前流中讀取最多的 count 個(gè)字節(jié),并將它們存儲(chǔ)在從 offset 開(kāi)始的 buffer 中。流中的當(dāng)前位置提升已讀取的字節(jié)數(shù);但是,如果出現(xiàn)異常,流中的當(dāng)前位置保持不變。實(shí)現(xiàn)返回已讀取的字節(jié)數(shù)。僅當(dāng)位置當(dāng)前位于流的末尾時(shí),返回值才為零。如果沒(méi)有任何可用的數(shù)據(jù),該實(shí)現(xiàn)將一直阻塞到至少有一個(gè)字節(jié)的數(shù)據(jù)可讀為止。僅當(dāng)流中不再有其他的數(shù)據(jù),而且也不再需要更多的數(shù)據(jù)(如已關(guān)閉的套接字或文件尾)時(shí),Read 才返回 0。即使尚未到達(dá)流的末尾,實(shí)現(xiàn)仍可以隨意返回少于所請(qǐng)求的字節(jié)。
 
請(qǐng)注意上述的 MSDN 中的最后一句話(huà)。我們寫(xiě)一個(gè)程序來(lái)驗(yàn)證這一點(diǎn):

using System;
using System.IO;
using Skyiv.Util;

namespace Skyiv.Ben.StreamTest
{
  sealed class Program
  {
    static void Main()
    {
      var bs = new byte[128 * 1024];
      var stream = new FtpClient("ftp://ftp.hp.com", "anonymous", "ben@skyiv.com").
        GetDownloadStream("pub/softpaq/allfiles.txt"); // 568,320 bytes
      var br = new BinaryReader(stream);
      Display("Expect", bs.Length);
      Display("Stream.Read", stream.Read(bs, 0, bs.Length));
      Display("BinaryReader.Read", br.Read(bs, 0, bs.Length));
      Display("BinaryReader.ReadBytes", br.ReadBytes(bs.Length).Length);
      Display("Stream.Readbytes", stream.ReadBytes(bs.Length).Length);
    }

    static void Display(string msg, int n)
    {
      Console.WriteLine("{0,22}: {1,7:N0}", msg, n);
    }
  }
}

將這個(gè)程序運(yùn)行三次的結(jié)果如下:

                Expect: 131,072
           Stream.Read:  50,604
     BinaryReader.Read:  11,616
BinaryReader.ReadBytes: 131,072
      Stream.Readbytes: 131,072

                Expect: 131,072
           Stream.Read:   1,452
     BinaryReader.Read:   2,904
BinaryReader.ReadBytes: 131,072
      Stream.Readbytes: 131,072

                Expect: 131,072
           Stream.Read:   4,356
     BinaryReader.Read: 131,072
BinaryReader.ReadBytes: 131,072
      Stream.Readbytes: 131,072


可見(jiàn),Stream.Read 方法和 BinaryReader.Read 方法在尚未到達(dá)流的末尾情況下可以返回少于所請(qǐng)求的字節(jié)。

通過(guò)使用 Reflector 來(lái)查看 BinaryReader.Read 方法的源程序代碼,如下:

public virtual int Read(byte[] buffer, int index, int count)
{
  if (buffer == null)
  {
    throw new ArgumentNullException
("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
  }
  if (index < 0)
  {
    throw new ArgumentOutOfRangeException
("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  }
  if (count < 0)
  {
    throw new ArgumentOutOfRangeException
("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  }
  if ((buffer.Length - index) < count)
  {
    throw new ArgumentException
(Environment.GetResourceString("Argument_InvalidOffLen"));
  }
  if (this.m_stream == null)
  {
    __Error.FileNotOpen();
  }
  return this.m_stream.Read(buffer, index, count);
}

上述代碼最后一行中 m_stream 的類(lèi)型為 Stream,就是 BinaryReader 類(lèi)的基礎(chǔ)流??梢?jiàn),BinaryReader.Read 方法在做一些必要的檢查后就是簡(jiǎn)單地調(diào)用 Stream.Read 方法。

而 BinaryReader.ReadBytes 方法的源程序代碼如下:

public virtual byte[] ReadBytes(int count)
{
  if (count < 0)
  {
    throw new ArgumentOutOfRangeException
("count", Environment.GetResourceString
       ("ArgumentOutOfRange_NeedNonNegNum"));
  }
  if (this.m_stream == null)
  {
    __Error.FileNotOpen();
  }
  byte[] buffer = new byte[count];
  int offset = 0;
  do
  {
    int num2 = this.m_stream.Read(buffer, offset, count);
    if (num2 == 0)
    {
      break;
    }
    offset += num2;
    count -= num2;
  }
  while (count > 0);
  if (offset != buffer.Length)
  {
    byte[] dst = new byte[offset];
    Buffer.InternalBlockCopy(buffer, 0, dst, 0, offset);
    buffer = dst;
  }
  return buffer;
}

從上述代碼中可以看出,BinaryReader.ReadBytes 方法循環(huán)地調(diào)用 Stream.Read 方法,直到達(dá)到流的末尾,或者已經(jīng)讀取了 count 個(gè)字節(jié)。也就是說(shuō),如果沒(méi)有到達(dá)流的末尾,該方法就一定會(huì)返回所請(qǐng)求的字節(jié)。

MSDN 文檔中對(duì)這兩個(gè)方法的描述:

BinaryReader.Read 方法:將 index 作為字節(jié)數(shù)組中的起始點(diǎn),從流中讀取 count 個(gè)字節(jié)。
BinaryReader.ReadBytes 方法:從當(dāng)前流中將 count 個(gè)字節(jié)讀入字節(jié)數(shù)組,并使當(dāng)前位置提升 count 個(gè)字節(jié)。
上述兩個(gè)方法的備注: BinaryReader 在讀取失敗后不還原文件位置。
 
也就是說(shuō),雖然 BinaryReader.Read 方法和 Stream.Read 方法一樣在尚未到達(dá)流的末尾情況下可以返回少于所請(qǐng)求的字節(jié),但是在 MSDN 文檔中并沒(méi)有指出這一點(diǎn),我們寫(xiě)程序的時(shí)候要小心,避免掉入這個(gè)陷阱。

上述的測(cè)試程序中用到了 Stream.ReadBytes 方法,其實(shí)是一個(gè)擴(kuò)展方法,源程序代碼如下:

using System;
using System.IO;

namespace Skyiv.Util
{
  static class ExtensionMethods
  {
    public static byte[] ReadBytes(this Stream stream, int count)
    {
 if (count < 0) throw new ArgumentOutOfRangeException("count", "要求非負(fù)數(shù)");
      var bs = new byte[count];
      var offset = 0;
      for (int n = -1; n != 0 && count > 0; count -= n, offset += n)

n = stream.Read(bs, offset, count);
      if (offset != bs.Length) Array.Resize(ref bs, offset);
      return bs;
    }
  }
}

上述的測(cè)試程序中還使用了 FtpClient 類(lèi),可以參見(jiàn)我的另一篇隨筆“如何直接處理FTP服務(wù)器上的壓縮文件”,其源程序代碼如下:

using System;
using System.IO;
using System.Net;

namespace Skyiv.Util
{
  sealed class FtpClient
  {
    Uri uri;
    string userName;
    string password;

    public FtpClient(string uri, string userName, string password)
    {
      this.uri = new Uri(uri);
      this.userName = userName;
      this.password = password;
    }

    public Stream GetDownloadStream(string sourceFile)
    {
      Uri downloadUri = new Uri(uri, sourceFile);
   if (downloadUri.Scheme != Uri.UriSchemeFtp)

throw new ArgumentException("URI is not an FTP site");
   FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(downloadUri);
      ftpRequest.Credentials = new NetworkCredential(userName, password);
      ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile;
      return ((FtpWebResponse)ftpRequest.GetResponse()).GetResponseStream();
    }
  }
}

我在上一篇隨筆“【算法】利用有限自動(dòng)機(jī)進(jìn)行字符串匹配”中給出了一道思考題如下:

上面的第二個(gè) C# 程序中有一個(gè) bug,但是這個(gè) bug 在絕大多數(shù)情況下都不會(huì)表現(xiàn)出來(lái)。所以這個(gè)程序能夠 Accepted。

親愛(ài)的讀者,你能夠找出這個(gè) bug 嗎?

提示,這個(gè) bug 和字符串匹配算法無(wú)關(guān),并且第一個(gè) C# 程序中不存在這個(gè) bug 。
 
上述思考題中的第二個(gè) C# 程序的 Main 方法如下所示:

static void Main()
{
  var s = new byte[10000000 + 2 * 1000 + 100];
  int i = 0, n = Console.OpenStandardInput().Read(s, 0, s.Length);
  while (s[i++] != '\n') ;
  for (int c, q = 0; i < n; q = 0)
  {
    while ((c = s[i++]) != '\n')
    if (q < 99 && c != '\r') q = delta[q, Array.IndexOf(a, c) + 1];
Console.WriteLine((q < 4) ? "YES" : "NO");
  }

這個(gè) bug 至今還沒(méi)有人找到。實(shí)際上,該方法的頭兩個(gè)語(yǔ)句應(yīng)改為:

var s = new BinaryReader
(Console.OpenStandardInput()).ReadBytes(10000000 + 2 * 1000 + 100);
int i = 0, n = s.Length; 

這是因?yàn)?Steam.Read 方法在尚未到達(dá)流的末尾情況下可以返回少于所請(qǐng)求的字節(jié),這有可能導(dǎo)致只讀取了部分輸入而產(chǎn)生 bug 。

【編輯推薦】

  1. 淺析.NET Framework中XML數(shù)據(jù)處理
  2. .net framework3.5新特性2:新增匿名類(lèi)
  3. 在.NET Framework 3.5中的WCF通信選項(xiàng)
責(zé)任編輯:彭凡 來(lái)源: cnblogs
相關(guān)推薦

2009-07-22 17:07:16

WPF插件開(kāi)發(fā).NET Framew

2009-06-29 10:19:42

.NET Micro性能優(yōu)化

2009-08-26 14:27:03

C# Framewor

2011-06-08 11:36:16

ASP.NETrender

2009-07-20 16:04:37

ASP.NET fra

2010-01-05 18:49:57

.NET Framew

2009-07-23 14:47:03

Page_Load方法ASP.NET

2010-01-05 16:20:46

.NET Framew

2011-06-28 09:51:08

.NET對(duì)象相等

2009-08-18 11:08:24

.Net Framew

2010-01-05 18:21:33

.NET Framew

2010-01-06 18:33:56

.Net Framew

2010-01-05 10:17:35

.NET Framew

2009-07-16 15:02:33

Shapes命名空間Net Micro F

2009-07-27 13:01:28

TreeViewASP.NET

2010-01-05 15:52:07

.NET Framew

2010-01-05 15:43:13

.NET Framew

2009-07-28 16:07:40

.NET圖片快速處理

2009-06-26 10:48:45

職責(zé)鏈模式.NET

2010-01-06 16:54:07

.Net Framew
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)