Afaik CLR託管堆將不會分配大於2 GB的任何內容,並且MemoryStream由活動的連續字節[]支持。 Large Object Heap的分配句柄不超過2GB,即使在x64上也沒有。
但是要將整個文件存儲在內存中只是爲了計算散列似乎是相當低的技術。您可以在收到字節時按塊計算哈希。在每個IO完成後,您可以散列接收到的字節,然後將寫入提交給文件。最後,你已經計算了和這個文件上傳的huraay。
順便說一句,如果你想尋找的代碼文件進行操作,避開一個包含詞語ReadToEnd
任何樣品的...
class Program
{
private static AutoResetEvent done = new AutoResetEvent(false);
private static AsyncCallback _callbackReadStream;
private static AsyncCallback _callbackWriteFile;
static void Main(string[] args)
{
try
{
_callbackReadStream = new AsyncCallback(CallbackReadStream);
_callbackWriteFile = new AsyncCallback(CallbackWriteFile);
string url = "http://...";
WebRequest request = WebRequest.Create(url);
request.Method = "GET";
request.BeginGetResponse(new AsyncCallback(
CallbackGetResponse), request);
done.WaitOne();
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
}
}
private class State
{
public Stream ReponseStream { get; set; }
public HashAlgorithm Hash { get; set; }
public Stream FileStream { get; set; }
private byte[] _buffer = new byte[16379];
public byte[] Buffer { get { return _buffer; } }
public int ReadBytes { get; set; }
public long FileLength {get;set;}
}
static void CallbackGetResponse(IAsyncResult ar)
{
try
{
WebRequest request = (WebRequest)ar.AsyncState;
WebResponse response = request.EndGetResponse(ar);
State s = new State();
s.ReponseStream = response.GetResponseStream();
s.FileStream = new FileStream("download.out"
, FileMode.Create
, FileAccess.Write
, FileShare.None);
s.Hash = HashAlgorithm.Create("MD5");
s.ReponseStream.BeginRead(
s.Buffer
, 0
, s.Buffer.Length
, _callbackReadStream
, s);
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
done.Set();
}
}
private static void CallbackReadStream(IAsyncResult ar)
{
try
{
State s = (State)ar.AsyncState;
s.ReadBytes = s.ReponseStream.EndRead(ar);
s.Hash.ComputeHash(s.Buffer, 0, s.ReadBytes);
s.FileStream.BeginWrite(
s.Buffer
, 0
, s.ReadBytes
, _callbackWriteFile
, s);
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
done.Set();
}
}
static private void CallbackWriteFile(IAsyncResult ar)
{
try
{
State s = (State)ar.AsyncState;
s.FileStream.EndWrite(ar);
s.FileLength += s.ReadBytes;
if (0 != s.ReadBytes)
{
s.ReponseStream.BeginRead(
s.Buffer
, 0
, s.Buffer.Length
, _callbackReadStream
, s);
}
else
{
Console.Out.Write("Downloaded {0} bytes. Hash(base64):{1}",
s.FileLength, Convert.ToBase64String(s.Hash.Hash));
done.Set();
}
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
done.Set();
}
}
}
當他說這是不是100%中解脫出來,被他指的是自動垃圾採集? – 2009-10-02 20:26:48
他很可能是。你可以打電話給GC。Collect()手動強制垃圾收集,但這是一個不好的習慣,特別是如果調用它的方法會被頻繁調用。 – Chris 2009-10-02 20:29:33
我的意思是,如果你在調用Dispose之後堅持一個'MemoryStream',那麼數據仍然存在 - 如果你調用'ToArray',你仍然可以獲取數據。在MemoryStream存儲之前,該數組不適用於收集。 – 2009-10-02 20:34:02