从stream中创build一个字节数组

从inputstream创build字节数组的首选方法是什么?

这是我目前使用.NET 3.5的解决scheme。

Stream s; byte[] b; using (BinaryReader br = new BinaryReader(s)) { b = br.ReadBytes((int)s.Length); } 

读取和写入stream的块是一个更好的主意吗?

这真的取决于你是否可以信任s.Length 。 对于许多stream,你只是不知道会有多less数据。 在这种情况下 – 和.NET 4之前 – 我会使用这样的代码:

 public static byte[] ReadFully(Stream input) { byte[] buffer = new byte[16*1024]; using (MemoryStream ms = new MemoryStream()) { int read; while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { ms.Write(buffer, 0, read); } return ms.ToArray(); } } 

与.NET 4及以上,我会使用Stream.CopyTo ,这基本上是相当于我的代码中的循环 – 创buildMemoryStream ,调用stream.CopyTo(ms) ,然后返回ms.ToArray() 。 任务完成。

我也许应该解释为什么我的答案比其他答案长。 Stream.Read不保证它会读取所有要求的东西。 例如,如果您正在从networkingstream中读取数据,则可能会读取一个数据包的值,然后返回,即使即将有更多的数据。 BinaryReader.Read将继续前进,直到stream的结束或您指定的大小,但您仍然必须知道大小开始。

上述方法将继续读取(并复制到MemoryStream中)直到数据用完。 然后它要求MemoryStream返回一个数组的数据副本。 如果您知道开始时的大小 – 或者认为您知道大小,但不确定 – 则可以将MemoryStream构build为开始时的大小。 同样,你可以在最后进行检查,如果stream的长度与缓冲区的大小相同(由MemoryStream.GetBuffer返回),那么你可以返回缓冲区。 所以上面的代码并没有被优化,但至less是正确的。 它不承担任何closuresstream的责任 – 调用者应该这样做。

看到这篇文章的更多信息(和一个替代的实现)。

Jon的回答是正确的,他正在重写CopyTo中已经存在的代码。 所以对于.Net 4使用Sandip的解决scheme,但对于以前版本的.Net使用乔恩的答案。 Sandip的代码可以通过使用“using”来改善,在很多情况下,CopyTo是非常可能的,并且不会丢弃MemoryStream。

 public static byte[] ReadFully(Stream input) { using (MemoryStream ms = new MemoryStream()) { input.CopyTo(ms); return ms.ToArray(); } } 

只是想指出,如果你有一个MemoryStream,你已经有memorystream.ToArray()

此外,如果您正在处理未知或不同子types的stream,并且您可以接收到一个MemoryStream ,则可以针对这些情况在该方法上进行中继,并仍然使用其他方法的接受答案,如下所示:

 public static byte[] StreamToByteArray(Stream stream) { if (stream is MemoryStream) { return ((MemoryStream)stream).ToArray(); } else { // Jon Skeet's accepted answer return ReadFully(stream); } } 
 MemoryStream ms = new MemoryStream(); file.PostedFile.InputStream.CopyTo(ms); var byts = ms.ToArray(); ms.Dispose(); 

只是我的夫妇美分…我经常使用的做法是组织像这样的方法作为一个习惯的帮手

 public static class StreamHelpers { public static byte[] ReadFully(this Stream input) { using (MemoryStream ms = new MemoryStream()) { input.CopyTo(ms); return ms.ToArray(); } } } 

将命名空间添加到configuration文件并将其用于任何你想要的地方

我得到了鲍勃(即提问者)代码的编译时错误。 Stream.Length很长,而BinaryReader.ReadBytes则是一个整型参数。 在我的情况下,我不希望处理Streams足够大,需要很长的精度,所以我使用以下内容:

 Stream s; byte[] b; if (s.Length > int.MaxValue) { throw new Exception("This stream is larger than the conversion algorithm can currently handle."); } using (var br = new BinaryReader(s)) { b = br.ReadBytes((int)s.Length); } 

你甚至可以使用扩展更有趣:

 namespace Foo { public static class Extensions { public static byte[] ToByteArray(this Stream stream) { using (stream) { using (MemoryStream memStream = new MemoryStream()) { stream.CopyTo(memStream); return memStream.ToArray(); } } } } } 

然后将其称为常规方法:

 byte[] arr = someStream.ToByteArray() 

上面的一个是好的…但是当你通过SMTP发送东西(如果你需要的话),你会遇到数据损坏。 我已经改变了其他东西,这将有助于正确发送字节的字节:'

 using System; using System.IO; private static byte[] ReadFully(string input) { FileStream sourceFile = new FileStream(input, FileMode.Open); //Open streamer BinaryReader binReader = new BinaryReader(sourceFile); byte[] output = new byte[sourceFile.Length]; //create byte array of size file for (long i = 0; i < sourceFile.Length; i++) output[i] = binReader.ReadByte(); //read until done sourceFile.Close(); //dispose streamer binReader.Close(); //dispose reader return output; }' 

你可以使用这个扩展方法。

 public static class StreamExtensions { public static byte[] ToByteArray(this Stream stream) { var bytes = new List<byte>(); int b; while ((b = stream.ReadByte()) != -1) bytes.Add((byte)b); return bytes.ToArray(); } } 

我能够使它在一条线上工作:

 byte [] byteArr= ((MemoryStream)localStream).ToArray(); 

由johnnyRose澄清,上面的代码将只适用于MemoryStream

 public static byte[] ToByteArray(Stream stream) { if (stream is MemoryStream) { return ((MemoryStream)stream).ToArray(); } else { byte[] buffer = new byte[16 * 1024]; using (MemoryStream ms = new MemoryStream()) { int read; while ((read = stream.Read(buffer, 0, buffer.Length)) > 0) { ms.Write(buffer, 0, read); } return ms.ToArray(); } } }