当我添加新数据时列出项目更改...为什么?

时间:2011-08-23 19:31:25

标签: c# list

我有一个将文件转换为字节的方法,以便稍后我可以通过互联网发送它。无论如何因为我打算发送大文件我发送文件块而不是发送整个文件。每个块由一个字节数组(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;
            }
        }


    }
}

当我执行时:

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

binaryFileList List使用文件块填充:A:\ Users \ Tono \ Desktop \ t.iso

现在我遇到问题就是从这个数据创建一个文件。在debuging时我注意到问题是因为我输入数据时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是byte []的列表。当我向binaryFileList添加一个byte []时,其他byte []不应该改变。他们确实改变了!为什么!?

6 个答案:

答案 0 :(得分:2)

以下行必须进入循环:

byte[] chunk = new byte[MaxChunkSize];

您只创建一次块,并且每次使用新数据覆盖它。您在列表中存储的内容只是对此块的引用,而不是它的副本。

答案 1 :(得分:1)

当您致电byte[]时,chunk使用stream.Read的相同引用。

答案 2 :(得分: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;
        }
    }

答案 3 :(得分:0)

我的猜测是你要重新使用传递给SendChunk方法的字节数组。数组是引用类型 - 您应该为每个方法调用创建一个新的字节数组。

答案 4 :(得分:0)

您继续将缓冲区变量添加到数组中,该数组将相同的引用放在每个列表位置的相同对象中。

您需要分配一个新的byte []并将缓冲区数组复制到该新数组中,或者为您读取的每个块分配一个新的缓冲区数组。

以下是Eric Lippert关于参考文献的两篇优秀文章,我建议你阅读以便更好地理解这个问题:

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

答案 5 :(得分:0)

问题是因为你只分配了一次块数组:

byte[] chunk = new byte[MaxChunkSize];

并且您正在反复读取同一数组的新文件部分。 请记住,数组作为方法参数中的引用传递。 在循环中移动声明,你应该没问题。