从输入流创建字节数组的首选方法是什么?
下面是我目前使用。net 3.5的解决方案。
Stream s;
byte[] b;
using (BinaryReader br = new BinaryReader(s))
{
b = br.ReadBytes((int)s.Length);
}
读写流的块仍然是一个更好的主意吗?
从输入流创建字节数组的首选方法是什么?
下面是我目前使用。net 3.5的解决方案。
Stream s;
byte[] b;
using (BinaryReader br = new BinaryReader(s))
{
b = br.ReadBytes((int)s.Length);
}
读写流的块仍然是一个更好的主意吗?
当前回答
如果有人喜欢它,这里有一个。net 4+的解决方案,它是一个扩展方法,没有对MemoryStream进行不必要的Dispose调用。这是一个无可救药的琐碎优化,但值得注意的是,未能Dispose MemoryStream并不是真正的失败。
public static class StreamHelpers
{
public static byte[] ReadFully(this Stream input)
{
var ms = new MemoryStream();
input.CopyTo(ms);
return ms.ToArray();
}
}
其他回答
虽然Jon的回答是正确的,但他正在重写CopyTo中已经存在的代码。所以对于。net 4使用Sandip的解决方案,但是对于以前版本的。net使用Jon的答案。Sandip的代码将通过使用“using”作为CopyTo中的异常而得到改进,在许多情况下,很可能会留下MemoryStream不被处理。
public static byte[] ReadFully(Stream input)
{
using (MemoryStream ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
这真的取决于你是否可以信任。对于许多流,你只是不知道会有多少数据。在这种情况下——在。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()。工作。
我也许应该解释一下为什么我的答案比其他人的长。流。Read不能保证它会读取所有要求的内容。例如,如果您正在从网络流中读取数据,它可能会读取一个数据包的值,然后返回,即使很快会有更多的数据。主题。Read将一直进行到流的结束或指定的大小,但您仍然必须知道开始时的大小。
The above method will keep reading (and copying into a MemoryStream) until it runs out of data. It then asks the MemoryStream to return a copy of the data in an array. If you know the size to start with - or think you know the size, without being sure - you can construct the MemoryStream to be that size to start with. Likewise you can put a check at the end, and if the length of the stream is the same size as the buffer (returned by MemoryStream.GetBuffer) then you can just return the buffer. So the above code isn't quite optimised, but will at least be correct. It doesn't assume any responsibility for closing the stream - the caller should do that.
有关更多信息(以及另一种实现),请参阅本文。
将两个投票最多的答案组合成一个扩展方法:
public static byte[] ToByteArray(this Stream stream)
{
if (stream is MemoryStream)
return ((MemoryStream)stream).ToArray();
else
{
using MemoryStream ms = new();
stream.CopyTo(ms);
return ms.ToArray();
}
}
由于这个答案没有现代(即异步)版本,这是我用于此目的的扩展方法:
public static async Task<byte[]> ReadAsByteArrayAsync(this Stream source)
{
// Optimization
if (source is MemoryStream memorySource)
return memorySource.ToArray();
using var memoryStream = new MemoryStream();
await source.CopyToAsync(memoryStream);
return memoryStream.ToArray();
}
这种优化是基于ToArray的源代码调用一些内部方法的事实。
你可以简单地使用MemoryStream类的ToArray()方法,对于ex-
MemoryStream ms = (MemoryStream)dataInStream;
byte[] imageBytes = ms.ToArray();