从输入流创建字节数组的首选方法是什么?
这是我目前使用.NET 3.5的解决方案.
Stream s; byte[] b; using (BinaryReader br = new BinaryReader(s)) { b = br.ReadBytes((int)s.Length); }
读取和写入流的块是否仍然是一个更好的主意?
这真的取决于你是否可以信任s.Length
.对于许多流,您只是不知道将有多少数据.在这种情况下 - 在.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
,这基本上等同于我的代码中的循环 - 创建MemoryStream
,调用stream.CopyTo(ms)
然后返回ms.ToArray()
.任务完成.
我或许应该解释为什么我的回答比其他人长.Stream.Read
并不保证它会读取它所要求的所有内容.例如,如果您正在从网络流中读取数据,它可能会读取一个数据包的值,然后返回,即使很快会有更多数据.BinaryReader.Read
将一直持续到流的末尾或您指定的大小,但您仍然必须知道开始的大小.
上述方法将继续读取(并复制到a MemoryStream
),直到数据耗尽为止.然后它要求MemoryStream
返回数组中的数据副本.如果您知道要开始的大小 - 或者认为您知道大小,而不确定 - 您可以构建该MemoryStream
大小开始.同样,您可以在结尾处进行检查,如果流的长度与缓冲区的大小相同(返回MemoryStream.GetBuffer
),则可以返回缓冲区.所以上面的代码并没有得到很好的优化,但至少是正确的.关闭流不承担任何责任 - 调用者应该这样做.
有关更多信息(以及替代实现),请参阅此文章.
虽然Jon的回答是正确的,但他正在重写已经存在的代码CopyTo
.因此.Net 4使用Sandip的解决方案,但对于.Net的早期版本使用Jon的答案.Sandip的代码将通过使用"使用"作为例外进行改进CopyTo
,在很多情况下很可能并且会使MemoryStream
未处理.
public static byte[] ReadFully(Stream input) { using (MemoryStream ms = new MemoryStream()) { input.CopyTo(ms); return ms.ToArray(); } }
只是想指出,如果你有一个MemoryStream你已经拥有memorystream.ToArray()
了.
此外,如果您正在处理未知或不同子类型的流并且您可以收到一个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(); } } }
将命名空间添加到配置文件并在任何地方使用它
您甚至可以通过扩展程序使其变得更加漂亮:
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()
你可以简单地使用MemoryStream类的ToArray()方法,
MemoryStream ms = (MemoryStream)dataInStream; byte[] imageBytes = ms.ToArray();
我得到了鲍勃(即提问者)代码的编译时错误.Stream.Length是long,而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); }