首页 文章

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

提问于
浏览
331

这个问题在这里已有答案:

是否有一种简单的方法或方法将 Stream 转换为C#中的 byte[]

12 回答

  • 145
    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;
    }
    

    需要稍微复杂的解决方案是 s.Length 超过 Int32.MaxValue . 但是如果你需要读取一个大到内存的流,你可能想要考虑一个不同的方法来解决你的问题 .

    编辑:如果您的流不支持 Length 属性,请使用Earwicker的workaround进行修改 .

    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();
    
  • 1

    “bigEnough”阵列有点紧张 . 当然,缓冲区需要“大量”,但应用程序的正确设计应包括事务和分隔符 . 在此配置中,每个事务都具有预设长度,因此您的阵列将预期特定数量的字节并将其插入到正确大小的缓冲区中 . 分隔符将确保交易完整性,并将在每笔交易中提供 . 为了使您的应用程序更好,您可以使用2个通道(2个插槽) . 人们将传达固定长度控制消息事务,其将包括关于要使用数据信道传输的数据事务的大小和序列号的信息 . 接收方将确认缓冲区创建,然后才会发送数据 . 如果您无法控制流发送方,则需要多维数组作为缓冲区 . 组件阵列足够小,易于管理,并且足够大,可根据您对预期数据的估计而实用 . 进程逻辑将寻找已知的起始分隔符,然后在后续元素数组中结束分隔符 . 一旦找到结束分隔符,将创建新的缓冲区以在分隔符之间存储相关数据,并且必须重新构造初始缓冲区以允许数据处理 .

    至于将流转换为字节数组的代码如下所示 .

    Stream s = yourStream;
    int streamEnd = Convert.ToInt32(s.Length);
    byte[] buffer = new byte[streamEnd];
    s.Read(buffer, 0, streamEnd);
    
  • 19

    我知道的最短解决方案:

    using(var memoryStream = new MemoryStream())
    {
      sourceStream.CopyTo(memoryStream);
      return memoryStream.ToArray();
    }
    
  • 15

    快速而肮脏的技术:

    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;
        }
    

    测试:

    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); 
        }
    

    我会问,为什么要将流读入byte [],如果您希望复制流的内容,我可以建议使用MemoryStream并将输入流写入内存流 .

  • 0

    您也可以尝试一次只读取部分并扩展返回的字节数组:

    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;
    }
    
  • 41

    在.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);
    }
    

    然后使用上述方法之一复制到 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: 最初我建议使用Jason的答案来支持 Length 属性 Stream . 但它有一个缺陷,因为它假设 Stream 将在单个 Read 中返回其所有内容,这不一定是真的(例如,不是 Socket . )我不知道是否有一个 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;
    

    也就是说,重复调用 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();
            }
        }
    }
    

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

    byte[] bytes = myStream.ReadAllBytes()
    

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

  • 2
    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
    
  • 27

    调用下一个函数就好

    byte[] m_Bytes = StreamHelper.ReadToEnd (mystream);
    

    功能:

    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; 
                }
            }
        }
    
  • 2
    Byte[] Content = new BinaryReader(file.InputStream).ReadBytes(file.ContentLength);
    
  • 702

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

    byte[] fileData = null;
        using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
        {
            fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
        }
    
  • 1

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

    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;
    }
    

相关问题