2011-08-23 92 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];

并且您正在将文件的新部分一次又一次地读入同一个阵列。 请记住,数组作为方法参数的参考传递。 在循环中移动声明,你应该没问题。

相关问题