2011-08-23 50 views
1

我有一種將文件轉換爲字節的方法,以便以後可以通過Internet發送它。無論如何,因爲我打算髮送大文件,我發送文件塊,而不是發送整個文件。每個塊由一個字節數組(byte [])組成。我是新手,所以我想在發送之前將每個塊保存在塊列表(List)中。所以我的課是這樣的:當我添加新數據時,列表項會發生變化...爲什麼?

public class SomeClass 
{ 

    public List<byte[]> binaryFileList; 

    public void SendChunk(byte[] data, int index) 
    { 
     binaryFileList.Add(data); 
     // later I will add code in here to do something with data 
    } 

    public void test(string path) 
    { 
     binaryFileList = new List<byte[]>(); 

     System.IO.FileStream stream = new System.IO.FileStream(path, 
      System.IO.FileMode.Open, System.IO.FileAccess.Read); 

     var MaxChunkSize = 10000; 
     byte[] chunk = new byte[MaxChunkSize]; 
     while (true) 
     { 
      int index = 0; 
      // There are various different ways of structuring this bit of code. 
      // Fundamentally we're trying to keep reading in to our chunk until 
      // either we reach the end of the stream, or we've read everything we need. 
      while (index < chunk.Length) 
      { 
       int bytesRead = stream.Read(chunk, index, chunk.Length - index); 

       if (bytesRead == 0) 
       { 
        break; 
       } 
       index += bytesRead; 
      } 
      if (index != 0) // Our previous chunk may have been the last one 
      { 
       SendChunk(chunk, index); // index is the number of bytes in the chunk 
      } 
      if (index != chunk.Length) // We didn't read a full chunk: we're done 
      { 
       return; 
      } 
     } 


    } 
} 

,當我執行:A:

SomeClass s = new SomeClass(); 
s.test(@"A:\Users\Tono\Desktop\t.iso"); 

binaryFileList列表獲取與文件塊填充\用戶\託諾\桌面\ t.iso

現在問題出現時,我綁定從該數據創建一個文件。在調試時我發現問題是因爲輸入數據時binaryFileList中的項發生了變化。讓我告訴你我是什麼意思:

enter image description here

通知,在此調試這是我第一次的項目添加到binaryFileList。也可以看到數組中的每個字節...

現在我將讓該方法運行多次,將更多項添加到binaryFileList中。

所以現在binaryFileList有278項,而不是一個喜歡在最後一張照片:

enter image description here

所以一切到目前爲止看起來不錯吧?但你們是否記得binaryFileList的第一項包含幾乎全爲0的字節數組?看看binaryFileList的第一項:

enter image description here

和我繼續將項目添加到binaryFileList注意的第一個項目如何變化:

enter image description here

換句話說binaryFileList是一個列表的字節[]。當我向binaryFileList添加一個byte []時,其他byte []不應該改變。他們確實改變了!爲什麼!?

回答

2

下面一行已去內環路:

byte[] chunk = new byte[MaxChunkSize]; 

你只有一次創建塊,並用新的數據,每次覆蓋它。你存儲在你的列表中,只是對這個塊的引用,而不是其副本。

1

當您撥打stream.Read時,對chunk使用相同的參考byte[]

0

我的猜測是你正在重新使用你傳遞給SendChunk方法的字節數組。數組是引用類型,你應該爲每個方法調用創建一個新的字節數組。

1

您每次都讀入同一塊,並且每次將具有最新值的相同塊添加到列表中。要糾正你需要創建一個新的byte []每次:

while (true) 
    { 
     // *** need to create new array each time... 
     var chunk = new byte[MaxChunkSize]; 

     int index = 0; 
     // There are various different ways of structuring this bit of code. 
     // Fundamentally we're trying to keep reading in to our chunk until 
     // either we reach the end of the stream, or we've read everything we need. 
     while (index < chunk.Length) 
     { 
      int bytesRead = stream.Read(chunk, index, chunk.Length - index); 

      if (bytesRead == 0) 
      { 
       break; 
      } 
      index += bytesRead; 
     } 
     if (index != 0) // Our previous chunk may have been the last one 
     { 
      SendChunk(chunk, index); // index is the number of bytes in the chunk 
     } 
     if (index != chunk.Length) // We didn't read a full chunk: we're done 
     { 
      return; 
     } 
    } 
+0

詹姆斯我從那裏得到該方法:http://stackoverflow.com/questions/5659189/how-to-split-a-large-file-into-chunks-in-c/5659258#5659258由於該文件是直到下次我打電話給Read方法時它纔會讀取下一個字節。那個方法在寫數據的時候就起作用了... –

+0

誰投了票,原因是什麼?當其他人回答時,我們中的許多人同時提出了相同的答案。吮吸得到反對票並且不知道爲什麼。 –

+0

@Tono:是的,但你沒有馬上使用它,你將它存儲在列表中,然後循環。數組創建一次(比如在理論位置1000),然後對字節數組@ 1000的引用被壓入列表中。當您循環讀取時,您正在讀取位於位置1000的字節[]中的新字節!這就是問題。如果要將它們存儲在某處(或在添加到列表之前將其克隆),則需要新的字節[]。無論哪種方式,您都需要爲每個想要存儲的數組創建一個數組。 –

0

你不斷增加你的緩衝區變量數組,這使相同的同一對象在每個列表中的位置。

您需要分配一個新的byte []並將緩衝區數組複製到該新數組中,或者爲您讀取的每個塊交替分配一個新的緩衝區數組。

這裏有引用一個優秀的兩部分後通過埃裏克利珀,我建議你閱讀,以便更好地理解這個問題:

http://blogs.msdn.com/b/ericlippert/archive/2011/03/07/references-and-pointers-part-one.aspx

http://blogs.msdn.com/b/ericlippert/archive/2011/03/10/references-and-pointers-part-two.aspx

0

的問題是,因爲你分配的塊陣列只有一次:

byte[] chunk = new byte[MaxChunkSize];

並且您正在將文件的新部分一次又一次地讀入同一個陣列。 請記住,數組作爲方法參數的參考傳遞。 在循環中移動聲明,你應該沒問題。

相關問題