我有一个将文件转换为字节的方法,以便稍后我可以通过互联网发送它。无论如何因为我打算发送大文件我发送文件块而不是发送整个文件。每个块由一个字节数组(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中的项目发生了变化。让我告诉你我的意思:
请注意,在此调试中,这是我第一次将项添加到binaryFileList。而且你也可以看到数组中该项目的每个字节...
现在我将让该方法运行更多次,为binaryFileList添加更多项目。
所以现在binaryFileList有278个项目而不是最后一个图片上的一个项目:
所以到目前为止一切看起来还不错?但是你们还记得binaryFileList的第一项包含一个几乎全为0的字节数组吗?看一下binaryFileList的第一项:
当我不断向binaryFileList添加项目时,请注意第一项如何更改:
换句话说,binaryFileList是byte []的列表。当我向binaryFileList添加一个byte []时,其他byte []不应该改变。他们确实改变了!为什么!?
答案 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];
并且您正在反复读取同一数组的新文件部分。 请记住,数组作为方法参数中的引用传递。 在循环中移动声明,你应该没问题。