如何在 C# 中将 Stream 转换为 byte[]?
在 C# 中是否有一种简单的方式或方法将 Stream
转换为 byte[]
?
Is there a simple way or method to convert a Stream
into a byte[]
in C#?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
我知道的最短的解决方案:
The shortest solution I know:
调用下一个函数,如
Function:
Call next function like
Function:
我使用这个扩展类:
只需将该类复制到您的解决方案中,您就可以在每个流上使用它:
非常适合我的所有流并节省大量代码!
当然,如果需要,您可以修改此方法以使用此处的一些其他方法来提高性能,但我喜欢保持简单。
I use this extension class:
Just copy the class to your solution and you can use it on every stream:
Works great for all my streams and saves a lot of code!
Of course you can modify this method to use some of the other approaches here to improve performance if needed, but I like to keep it simple.
在 .NET Framework 4 及更高版本中,
Stream
类具有可供您使用的内置CopyTo
方法。对于框架的早期版本,方便的辅助函数是:
然后使用上述方法之一复制到
MemoryStream
并对其调用GetBuffer
:编辑:最初我建议使用Jason的答案来支持
Length
属性的Stream
。 但它有一个缺陷,因为它假设Stream
将在一次Read
中返回其所有内容,这不一定是正确的(不适用于Socket
例如。)我不知道 BCL 中是否有Stream
实现的示例,它确实支持Length
但可能以较短的块返回数据比您请求的要多,但由于任何人都可以继承Stream
,这种情况很容易发生。对于大多数情况,使用上述通用解决方案可能更简单,但假设您确实想直接读取
bigEnough
的数组:也就是说,重复调用
Read
并移动您将存储数据的位置。In .NET Framework 4 and later, the
Stream
class has a built-inCopyTo
method that you can use.For earlier versions of the framework, the handy helper function to have is:
Then use one of the above methods to copy to a
MemoryStream
and callGetBuffer
on it:Edit: originally I suggested using Jason's answer for a
Stream
that supports theLength
property. But it had a flaw because it assumed that theStream
would return all its contents in a singleRead
, which is not necessarily true (not for aSocket
, for example.) I don't know if there is an example of aStream
implementation in the BCL that does supportLength
but might return the data in shorter chunks than you request, but as anyone can inheritStream
this could easily be the case.It's probably simpler for most cases to use the above general solution, but supposing you did want to read directly into an array that is
bigEnough
:That is, repeatedly call
Read
and move the position you will be storing the data at.好吧,也许我在这里遗漏了一些东西,但这就是我这样做的方式:
Ok, maybe I'm missing something here, but this is the way I do it:
如果您从移动设备或其他设备发布文件
if you post a file from mobile device or other
需要稍微复杂一点的解决方案是
s.Length
超过Int32.MaxValue
。 但是,如果您需要将这么大的流读取到内存中,您可能需要考虑采用不同的方法来解决问题。编辑:如果您的流不支持
Length
属性,请使用 Earwicker 的 解决方法。A slightly more complicated solution is necesary is
s.Length
exceedsInt32.MaxValue
. But if you need to read a stream that large into memory, you might want to think about a different approach to your problem.Edit: If your stream does not support the
Length
property, modify using Earwicker's workaround.快速而肮脏的技术:
测试:
我会问,为什么要将流读入 byte[],如果您希望复制流的内容,我可以建议使用 MemoryStream 并将输入流写入内存溪流。
Quick and dirty technique:
Test:
I would ask, why do you want to read a stream into a byte[], if you are wishing to copy the contents of a stream, may I suggest using MemoryStream and writing your input stream into a memory stream.
您还可以尝试一次只读取部分内容并扩展返回的字节数组:
You could also try just reading in parts at a time and expanding the byte array being returned:
“bigEnough”数组有点牵强。 当然,缓冲区需要“大”,但应用程序的正确设计应该包括事务和分隔符。 在此配置中,每个事务都有一个预设长度,因此您的数组将预期一定数量的字节并将其插入到正确大小的缓冲区中。 分隔符将确保事务完整性,并将在每个事务中提供。 为了使您的应用程序变得更好,您可以使用 2 个通道(2 个套接字)。 人们将传送固定长度的控制消息事务,该消息事务将包括关于要使用数据通道传输的数据事务的大小和序列号的信息。 接收器将确认缓冲区创建,然后才发送数据。
如果您无法控制流发送方,则需要多维数组作为缓冲区。 根据您对预期数据的估计,组件数组将足够小以便易于管理,并且足够大以便实用。 处理逻辑将在后续元素数组中寻找已知的开始分隔符,然后寻找结束分隔符。 一旦找到结束分隔符,将创建新的缓冲区来存储分隔符之间的相关数据,并且必须重组初始缓冲区以允许数据处理。
至于将流转换为字节数组的代码如下。
"bigEnough" array is a bit of a stretch. Sure, buffer needs to be "big ebough" but proper design of an application should include transactions and delimiters. In this configuration each transaction would have a preset length thus your array would anticipate certain number of bytes and insert it into correctly sized buffer. Delimiters would ensure transaction integrity and would be supplied within each transaction. To make your application even better, you could use 2 channels (2 sockets). One would communicate fixed length control message transactions that would include information about size and sequence number of data transaction to be transferred using data channel. Receiver would acknowledge buffer creation and only then data would be sent.
If you have no control over stream sender than you need multidimensional array as a buffer. Component arrays would be small enough to be manageable and big enough to be practical based on your estimate of expected data. Process logic would seek known start delimiters and then ending delimiter in subsequent element arrays. Once ending delimiter is found, new buffer would be created to store relevant data between delimiters and initial buffer would have to be restructured to allow data disposal.
As far as a code to convert stream into byte array is one below.