如何在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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章