本文翻译自:How to convert an Stream into a byte[] in C#? [duplicate]
This question already has an answer here: 这个问题在这里已有答案:
- Creating a byte array from a stream 16 answers 从流中创建一个字节数组 16个答案
Is there a simple way or method to convert an Stream
into a byte[]
in C#? 有没有一种简单的方法或方法将Stream
转换为C#中的byte[]
?
#1楼
参考:https://stackoom.com/question/4X4U/如何在C-中将Stream转换为byte-重复
#2楼
Call next function like 调用下一个函数就好
byte[] m_Bytes = StreamHelper.ReadToEnd (mystream);
Function: 功能:
public static byte[] ReadToEnd(System.IO.Stream stream)
{
long originalPosition = 0;
if(stream.CanSeek)
{
originalPosition = stream.Position;
stream.Position = 0;
}
try
{
byte[] readBuffer = new byte[4096];
int totalBytesRead = 0;
int bytesRead;
while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
{
totalBytesRead += bytesRead;
if (totalBytesRead == readBuffer.Length)
{
int nextByte = stream.ReadByte();
if (nextByte != -1)
{
byte[] temp = new byte[readBuffer.Length * 2];
Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
readBuffer = temp;
totalBytesRead++;
}
}
}
byte[] buffer = readBuffer;
if (readBuffer.Length != totalBytesRead)
{
buffer = new byte[totalBytesRead];
Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
}
return buffer;
}
finally
{
if(stream.CanSeek)
{
stream.Position = originalPosition;
}
}
}
#3楼
Stream s;
int len = (int)s.Length;
byte[] b = new byte[len];
int pos = 0;
while((r = s.Read(b, pos, len - pos)) > 0) {
pos += r;
}
A slightly more complicated solution is necesary is s.Length
exceeds Int32.MaxValue
. 需要稍微复杂的解决方案是s.Length
超过Int32.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 . 编辑:如果您的流不支持Length
属性,请使用Earwicker的变通方法进行修改。
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();
#4楼
Quick and dirty technique: 快速而肮脏的技术:
static byte[] StreamToByteArray(Stream inputStream)
{
if (!inputStream.CanRead)
{
throw new ArgumentException();
}
// This is optional
if (inputStream.CanSeek)
{
inputStream.Seek(0, SeekOrigin.Begin);
}
byte[] output = new byte[inputStream.Length];
int bytesRead = inputStream.Read(output, 0, output.Length);
Debug.Assert(bytesRead == output.Length, "Bytes read from stream matches stream length");
return output;
}
Test: 测试:
static void Main(string[] args)
{
byte[] data;
string path = @"C:\Windows\System32\notepad.exe";
using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read))
{
data = StreamToByteArray(fs);
}
Debug.Assert(data.Length > 0);
Debug.Assert(new FileInfo(path).Length == data.Length);
}
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. 我想问一下,为什么要将流读入byte [],如果您希望复制流的内容,我可以建议使用MemoryStream并将输入流写入内存流。
#5楼
In .NET Framework 4 and later, the Stream
class has a built-in CopyTo
method that you can use. 在.NET Framework 4及更高版本中, Stream
类具有可以使用的内置CopyTo
方法。
For earlier versions of the framework, the handy helper function to have is: 对于框架的早期版本,方便的帮助函数具有:
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);
}
Then use one of the above methods to copy to a MemoryStream
and call GetBuffer
on it: 然后使用上述方法之一复制到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
Edit: originally I suggested using Jason's answer for a Stream
that supports the Length
property. 编辑:最初我建议使用Jason的答案来获得支持Length
属性的Stream
。 But it had a flaw because it assumed that the Stream
would return all its contents in a single Read
, which is not necessarily true (not for a Socket
, for example.) I don't know if there is an example of a Stream
implementation in the BCL that does support Length
but might return the data in shorter chunks than you request, but as anyone can inherit Stream
this could easily be the case. 但它有一个缺陷,因为它假设Stream
将在单个Read
返回其所有内容,这不一定是真的(例如,不适用于Socket
。)我不知道是否有Stream
实现的示例在BCL中支持Length
但可能以比您请求更短的块返回数据,但是任何人都可以继承Stream
这很容易就是这种情况。
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
: 对于大多数情况来说,使用上面的一般解决方案可能更简单,但假设您确实想要直接读入一个bigEnough
的数组:
byte[] b = new byte[bigEnough];
int r, offset;
while ((r = input.Read(b, offset, b.Length - offset)) > 0)
offset += r;
That is, repeatedly call Read
and move the position you will be storing the data at. 也就是说,重复调用Read
并移动您将存储数据的位置。
#6楼
You could also try just reading in parts at a time and expanding the byte array being returned: 您也可以尝试一次只读取部分并扩展返回的字节数组:
public byte[] StreamToByteArray(string fileName)
{
byte[] total_stream = new byte[0];
using (Stream input = File.Open(fileName, FileMode.Open, FileAccess.Read))
{
byte[] stream_array = new byte[0];
// Setup whatever read size you want (small here for testing)
byte[] buffer = new byte[32];// * 1024];
int read = 0;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
stream_array = new byte[total_stream.Length + read];
total_stream.CopyTo(stream_array, 0);
Array.Copy(buffer, 0, stream_array, total_stream.Length, read);
total_stream = stream_array;
}
}
return total_stream;
}