public static class StreamExtensions {
// Credit to Earwicker
public static void CopyStream(this Stream input, Stream output) {
byte[] b = new byte[32768];
int r;
while ((r = input.Read(b, 0, b.Length)) > 0) {
output.Write(b, 0, r);
}
}
}
[...]
Stream s;
MemoryStream ms = new MemoryStream();
s.CopyStream(ms);
byte[] b = ms.GetBuffer();
public static void CopyStream(Stream input, Stream output)
{
byte[] b = new byte[32768];
int r;
while ((r = input.Read(b, 0, b.Length)) > 0)
output.Write(b, 0, r);
}
然后使用上述方法之一复制到 MemoryStream 并在其上调用 GetBuffer :
var file = new FileStream("c:\\foo.txt", FileMode.Open);
var mem = new MemoryStream();
// If using .NET 4 or later:
file.CopyTo(mem);
// Otherwise:
CopyStream(file, mem);
// getting the internal buffer (no additional copying)
byte[] buffer = mem.GetBuffer();
long length = mem.Length; // the actual length of the data
// (the array may be longer)
// if you need the array to be exactly as long as the data
byte[] truncated = mem.ToArray(); // makes another copy
byte[] b = new byte[bigEnough];
int r, offset;
while ((r = input.Read(b, offset, b.Length - offset)) > 0)
offset += r;
也就是说,重复调用 Read 并移动您将存储数据的位置 .
6
我使用这个扩展类:
public static class StreamExtensions
{
public static byte[] ReadAllBytes(this Stream instream)
{
if (instream is MemoryStream)
return ((MemoryStream) instream).ToArray();
using (var memoryStream = new MemoryStream())
{
instream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
}
12 回答
需要稍微复杂的解决方案是
s.Length
超过Int32.MaxValue
. 但是如果你需要读取一个大到内存的流,你可能想要考虑一个不同的方法来解决你的问题 .编辑:如果您的流不支持
Length
属性,请使用Earwicker的workaround进行修改 .“bigEnough”阵列有点紧张 . 当然,缓冲区需要“大量”,但应用程序的正确设计应包括事务和分隔符 . 在此配置中,每个事务都具有预设长度,因此您的阵列将预期特定数量的字节并将其插入到正确大小的缓冲区中 . 分隔符将确保交易完整性,并将在每笔交易中提供 . 为了使您的应用程序更好,您可以使用2个通道(2个插槽) . 人们将传达固定长度控制消息事务,其将包括关于要使用数据信道传输的数据事务的大小和序列号的信息 . 接收方将确认缓冲区创建,然后才会发送数据 . 如果您无法控制流发送方,则需要多维数组作为缓冲区 . 组件阵列足够小,易于管理,并且足够大,可根据您对预期数据的估计而实用 . 进程逻辑将寻找已知的起始分隔符,然后在后续元素数组中结束分隔符 . 一旦找到结束分隔符,将创建新的缓冲区以在分隔符之间存储相关数据,并且必须重新构造初始缓冲区以允许数据处理 .
至于将流转换为字节数组的代码如下所示 .
我知道的最短解决方案:
快速而肮脏的技术:
测试:
我会问,为什么要将流读入byte [],如果您希望复制流的内容,我可以建议使用MemoryStream并将输入流写入内存流 .
您也可以尝试一次只读取部分并扩展返回的字节数组:
在.NET Framework 4及更高版本中,
Stream
类具有可以使用的内置CopyTo
方法 .对于框架的早期版本,方便的帮助函数具有:
然后使用上述方法之一复制到
MemoryStream
并在其上调用GetBuffer
:Edit: 最初我建议使用Jason的答案来支持
Length
属性Stream
. 但它有一个缺陷,因为它假设Stream
将在单个Read
中返回其所有内容,这不一定是真的(例如,不是Socket
. )我不知道是否有一个Stream
实现的示例在BCL中支持Length
,但可能会以比您请求更短的块返回数据,但是任何人都可以继承Stream
,这很容易就是这种情况 .对于大多数情况来说,使用上面的通用解决方案可能更简单,但假设您确实想要直接读入
bigEnough
数组:也就是说,重复调用
Read
并移动您将存储数据的位置 .我使用这个扩展类:
只需将类复制到您的解决方案中,您就可以在每个流上使用它:
适用于我的所有流,并保存了大量代码!当然,如果需要,您可以修改此方法以使用其他一些方法来提高性能,但我希望保持简单 .
调用下一个函数就好
功能:
如果您从移动设备或其他人发布文件
好吧,也许我在这里遗漏了一些东西,但这就是我这样做的方式: