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

本文翻译自:How to convert an Stream into a byte[] in C#? [duplicate]

This question already has an answer here: 这个问题在这里已有答案:

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在C#中获取RTSP视频流并将其显示在PictureBox上,你可以使用FFmpeg和Windows Forms来完成。以下是一个简单的示例代码: 首先,确保你已经安装了FFmpeg,并将其路径添加到系统环境变量中。 然后,在Windows Forms应用程序中,你需要添加一个PictureBox控件和一个Button控件。当点击按钮时,将触发获取RTSP视频流并显示在PictureBox上的操作。 ```csharp using System; using System.Diagnostics; using System.Drawing; using System.IO; using System.Windows.Forms; namespace RTSPPlayer { public partial class Form1 : Form { private Process ffmpegProcess; private Stream ffmpegOutput; public Form1() { InitializeComponent(); } private void btnStart_Click(object sender, EventArgs e) { string rtspUrl = "rtsp://example.com/stream"; // RTSP流的URL // 使用FFmpeg启动一个子进程来接收RTSP流 ProcessStartInfo startInfo = new ProcessStartInfo { FileName = "ffmpeg", Arguments = $"-i {rtspUrl} -f image2pipe -vcodec rawvideo -pix_fmt rgb24 -", RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true }; ffmpegProcess = new Process(); ffmpegProcess.StartInfo = startInfo; ffmpegProcess.OutputDataReceived += FfmpegOutputDataReceived; // 启动FFmpeg进程 ffmpegProcess.Start(); // 打开输出流 ffmpegOutput = ffmpegProcess.StandardOutput.BaseStream; // 开始异步读取输出流 ffmpegProcess.BeginOutputReadLine(); } private void FfmpegOutputDataReceived(object sender, DataReceivedEventArgs e) { if (!String.IsNullOrEmpty(e.Data)) { // 处理视频帧数据 byte[] frameData = Convert.FromBase64String(e.Data); // 在UI线程中更新PictureBox的图像 pictureBox.Invoke(new Action(() => { using (MemoryStream ms = new MemoryStream(frameData)) { Image image = Image.FromStream(ms); pictureBox.Image = image; } })); } } private void btnStop_Click(object sender, EventArgs e) { // 停止FFmpeg进程和流读取 ffmpegProcess.Kill(); ffmpegOutput.Close(); ffmpegProcess = null; ffmpegOutput = null; // 清空PictureBox的图像 pictureBox.Image = null; } } } ``` 在上述代码中,我们通过启动一个子进程来执行FFmpeg命令,将RTSP视频流转换为RGB格式的原始视频帧数据,并将其读取到内存流中。然后,在UI线程中将图像显示在PictureBox上。 请注意,上述代码只是一个简单的示例,你可能需要根据实际需求进行修改和扩展。另外,为了避免阻塞UI线程,你可能需要使用异步操作来读取FFmpeg的输出流数据。 希望这可以帮助到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值