如何在C#中将Stream转换为byte []?

pup*_*eno 351 c# bytearray inputstream

有没有一种简单的方法或方法可以将其Stream转换为byte[]C#?

Jam*_*gle 767

我知道的最短解决方案:

using(var memoryStream = new MemoryStream())
{
  sourceStream.CopyTo(memoryStream);
  return memoryStream.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

  • 附注:CopyTo仅适用于.NET Framework 4. (68认同)
  • `MemoryStream`是`IDisposable` - 它不应该包含在`using`中吗? (9认同)
  • 是的,它确实.您可以使用MemoryStream.GetBuffer()来避免额外的副本,但要注意返回的数组大小不是数据的大小. (6认同)
  • 如果预先知道源流的长度,则最好使用此长度指定MemoryStream的容量; 内部缓冲区将具有适当的大小.如果长度未知,则写入MemoryStream意味着在写入数据和扩展缓冲区时内部缓冲区的潜在多个副本,在这种情况下,ToArray的额外副本不一定是主要问题. (3认同)
  • 更正。在 MemoryStream 的情况下没有真正的需要(挖掘源代码,它什么都不做),但这可能会改变。 (2认同)

ped*_*des 152

调用下一个函数就好

byte[] m_Bytes = StreamHelper.ReadToEnd (mystream);
Run Code Online (Sandbox Code Playgroud)

功能:

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; 
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 不确定我是否同意那里的Length*2缓冲区扩展策略. (20认同)
  • 如果您希望能够读取任意长度的流,几乎所有这些都是需要的。您可以使用 List<byte> 并保存一些代码.. (2认同)
  • 一大堆问题在一个大方法中混合在一起.是的,这一切都必须完成,但不是全部都在一个功能中.有可扩展的字节数组,并且有流读取.如果他们分开,就更容易纠正. (2认同)
  • 通过使用 MemoryStream 可以使代码变得更简单...... (2认同)

Dan*_*ker 44

在.NET Framework 4及更高版本中,Stream该类具有CopyTo可以使用的内置方法.

对于框架的早期版本,方便的帮助函数是:

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);
}
Run Code Online (Sandbox Code Playgroud)

然后使用上述方法之一复制到a 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
Run Code Online (Sandbox Code Playgroud)

编辑:最初我建议使用Jason的答案来Stream支持该Length属性.但它有一个缺陷,因为它假设Stream将所有内容返回到一个单独的Read,这不一定是真的(Socket例如,不是a ).我不知道Stream在BCL中是否有一个实现的例子确实支持Length但可能会以比您请求的更短的块返回数据,但是任何人都Stream可以轻易地继承这种情况.

对于大多数情况来说,使用上述通用解决方案可能更简单,但假设您确实希望直接读入以下数组bigEnough:

byte[] b = new byte[bigEnough];
int r, offset;
while ((r = input.Read(b, offset, b.Length - offset)) > 0)
    offset += r;
Run Code Online (Sandbox Code Playgroud)

也就是说,重复调用Read并移动您将存储数据的位置.


小智 27

    byte[] buf;  // byte array
    Stream stream=Page.Request.InputStream;  //initialise new stream
    buf = new byte[stream.Length];  //declare arraysize
    stream.Read(buf, 0, buf.Length); // read from stream to byte array
Run Code Online (Sandbox Code Playgroud)

  • 如果我没记错,"Read"并不总是从流中读取整个可用数量 - 例如请求N个字节,返回M个字节,M <N.因此,各种方法构建缓冲区并读取多次.https://msdn.microsoft.com/en-us/library/system.io.stream.read(v=vs.110).aspx (3认同)

JCH*_*H2k 23

我使用这个扩展类:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

只需将类复制到您的解决方案中,您就可以在每个流上使用它:

byte[] bytes = myStream.ReadAllBytes()
Run Code Online (Sandbox Code Playgroud)

适用于我的所有流,并保存了大量代码!当然,如果需要,您可以修改此方法以使用其他一些方法来提高性能,但我希望保持简单.

  • 使用 C# 7 效果更好:“if (instream is MemoryStream memoryStream) return memoryStream.ToArray();” (3认同)

小智 18

Byte[] Content = new BinaryReader(file.InputStream).ReadBytes(file.ContentLength);
Run Code Online (Sandbox Code Playgroud)

  • 很好,但是 `BinaryReader` 是一次性的,所以应该使用 `using`。 (3认同)

Sav*_*dar 7

如果您从移动设备或其他设备发布文件

    byte[] fileData = null;
    using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
    {
        fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
    }
Run Code Online (Sandbox Code Playgroud)


Vin*_*ius 6

好吧,也许我在这里遗漏了一些东西,但这就是我这样做的方式:

public static Byte[] ToByteArray(this Stream stream) {
    Int32 length = stream.Length > Int32.MaxValue ? Int32.MaxValue : Convert.ToInt32(stream.Length);
    Byte[] buffer = new Byte[length];
    stream.Read(buffer, 0, length);
    return buffer;
}
Run Code Online (Sandbox Code Playgroud)

  • 这个问题是 Stream.Read 并不总是读取“length”字节 - 它可以决定读取更少的数据(并返回实际读取的字节数)。您*必须*在循环中调用它以使其普遍工作! (3认同)

jas*_*son 5

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;
}
Run Code Online (Sandbox Code Playgroud)

一个稍微复杂的解决方案是必要s.LengthInt32.MaxValue。但是,如果您需要将这么大的流读取到内存中,您可能需要考虑采用不同的方法来解决问题。

编辑:如果您的流不支持该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();
Run Code Online (Sandbox Code Playgroud)