C# 从流创建字节数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/221925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Creating a byte array from a stream
提问by Bob
What is the prefered method for creating a byte array from an input stream?
从输入流创建字节数组的首选方法是什么?
Here is my current solution with .NET 3.5.
这是我当前使用 .NET 3.5 的解决方案。
Stream s;
byte[] b;
using (BinaryReader br = new BinaryReader(s))
{
b = br.ReadBytes((int)s.Length);
}
Is it still a better idea to read and write chunks of the stream?
读取和写入流的块仍然是一个更好的主意吗?
采纳答案by Jon Skeet
It really depends on whether or not you can trust s.Length
. For many streams, you just don't know how much data there will be. In such cases - and before .NET 4 - I'd use code like this:
这真的取决于您是否可以信任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();
}
}
With .NET 4 and above, I'd use Stream.CopyTo
, which is basically equivalent to the loop in my code - create the MemoryStream
, call stream.CopyTo(ms)
and then return ms.ToArray()
. Job done.
对于 .NET 4 及更高版本,我会使用Stream.CopyTo
,它基本上等同于我的代码中的循环 - 创建MemoryStream
, callstream.CopyTo(ms)
然后 return ms.ToArray()
。任务完成。
I should perhaps explain why my answer is longer than the others. Stream.Read
doesn't guarantee that it will read everything it's asked for. If you're reading from a network stream, for example, it may read one packet's worth and then return, even if there will be more data soon. BinaryReader.Read
will keep going until the end of the stream or your specified size, but you still have to know the size to start with.
我或许应该解释一下为什么我的答案比其他答案长。Stream.Read
不保证它会读取它要求的所有内容。例如,如果您正在从网络流中读取数据,它可能会读取一个数据包的价值然后返回,即使很快就会有更多数据。BinaryReader.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 thinkyou 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.
上述方法将继续读取(并复制到 a 中MemoryStream
),直到数据用完为止。然后它要求MemoryStream
返回一个数组中数据的副本。如果您知道开始时的尺寸 - 或者认为您知道尺寸,但不确定 - 您可以MemoryStream
将尺寸构建为开始时的尺寸。同样,您可以在末尾进行检查,如果流的长度与缓冲区的大小相同(由 返回MemoryStream.GetBuffer
),那么您可以只返回缓冲区。所以上面的代码没有完全优化,但至少是正确的。它不承担关闭流的任何责任 - 调用者应该这样做。
See this articlefor more info (and an alternative implementation).
有关更多信息(以及替代实现),请参阅本文。
回答by Fernando Neira
Just want to point out that in case you have a MemoryStream you already have memorystream.ToArray()
for that.
只是想指出,如果你有一个 MemoryStream,你已经拥有memorystream.ToArray()
了。
Also, if you are dealing with streams of unknown or different subtypes and you can receive a MemoryStream
, you can relay on said method for those cases and still use the accepted answer for the others, like this:
此外,如果您正在处理未知或不同子类型的流,并且您可以收到MemoryStream
,您可以在这些情况下中继所述方法,并且仍然使用其他人接受的答案,如下所示:
public static byte[] StreamToByteArray(Stream stream)
{
if (stream is MemoryStream)
{
return ((MemoryStream)stream).ToArray();
}
else
{
// Jon Skeet's accepted answer
return ReadFully(stream);
}
}
回答by Sandip Patel
MemoryStream ms = new MemoryStream();
file.PostedFile.InputStream.CopyTo(ms);
var byts = ms.ToArray();
ms.Dispose();
回答by Brian Hinchey
I get a compile time error with Bob's (i.e. the questioner's) code. Stream.Length is a long whereas BinaryReader.ReadBytes takes an integer parameter. In my case, I do not expect to be dealing with Streams large enough to require long precision, so I use the following:
我收到 Bob 的(即提问者的)代码编译时错误。Stream.Length 是一个 long 而 BinaryReader.ReadBytes 接受一个整数参数。就我而言,我不希望处理大到需要长精度的流,因此我使用以下内容:
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);
}
回答by Nathan Phillips
While Jon's answer is correct, he is rewriting code that already exists in CopyTo
. So for .Net 4 use Sandip's solution, but for previous version of .Net use Jon's answer. Sandip's code would be improved by use of "using" as exceptions in CopyTo
are, in many situations, quite likely and would leave the MemoryStream
not disposed.
虽然 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();
}
}
回答by Michal T
You can even make it fancier with extensions:
你甚至可以通过扩展让它更漂亮:
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();
}
}
}
}
}
And then call it as a regular method:
然后将其作为常规方法调用:
byte[] arr = someStream.ToByteArray()
回答by NothinRandom
The one above is ok...but you will encounter data corruption when you send stuff over SMTP (if you need to). I've altered to something else that will help to correctly send byte for byte: '
上面的那个没问题……但是当你通过 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;
}'
回答by Mr. Pumpkin
just my couple cents... the practice that I often use is to organize the methods like this as a custom helper
只是我的几分钱......我经常使用的做法是将这样的方法组织为自定义助手
public static class StreamHelpers
{
public static byte[] ReadFully(this Stream input)
{
using (MemoryStream ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
}
add namespace to the config file and use it anywhere you wish
将命名空间添加到配置文件并在您希望的任何地方使用它
回答by Abba
i was able to make it work on a single line:
我能够让它在一行上工作:
byte [] byteArr= ((MemoryStream)localStream).ToArray();
as clarified by johnnyRose, Above code will only work for MemoryStream
正如johnnyRose所澄清的,上面的代码只适用于 MemoryStream
回答by ?nder ?albay
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();
}
}
}