1088 Stimmen

Erstellen eines Byte-Arrays aus einem Stream

Was ist die bevorzugte Methode zur Erstellung eines Byte-Arrays aus einem Eingabestrom?

Hier ist meine aktuelle Lösung mit .NET 3.5.

Stream s;
byte[] b;

using (BinaryReader br = new BinaryReader(s))
{
    b = br.ReadBytes((int)s.Length);
}

Ist es immer noch eine bessere Idee, Teile des Datenstroms zu lesen und zu schreiben?

1455voto

Jon Skeet Punkte 1325502

Es hängt wirklich davon ab, ob Sie den folgenden Dingen vertrauen können oder nicht s.Length . Bei vielen Datenströmen weiß man einfach nicht, wie viele Daten anfallen werden. In solchen Fällen - und vor .NET 4 - würde ich Code wie diesen verwenden:

public static byte[] ReadFully(Stream input)
{
    byte[] buffer = new byte[16*1024];
    using (MemoryStream ms = new MemoryStream())
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, read);
        }
        return ms.ToArray();
    }
}

Mit .NET 4 und höher, würde ich verwenden Stream.CopyTo , was im Grunde der Schleife in meinem Code entspricht - die MemoryStream anrufen stream.CopyTo(ms) und dann zurück ms.ToArray() . Auftrag erledigt.

Ich sollte vielleicht erklären, warum meine Antwort länger ist als die der anderen. Stream.Read garantiert nicht, dass es alles liest, wonach es gefragt wird. Wenn Sie z. B. aus einem Netzwerkstrom lesen, kann es sein, dass er ein Paket liest und dann zurückkehrt, auch wenn es bald mehr Daten geben wird. BinaryReader.Read wird bis zum Ende des Streams oder der von Ihnen angegebenen Größe fortgesetzt, aber Sie müssen trotzdem die Größe kennen, mit der Sie beginnen.

Die obige Methode liest (und kopiert in eine MemoryStream ), bis die Daten aufgebraucht sind. Dann fragt er die MemoryStream um eine Kopie der Daten in einem Array zurückzugeben. Wenn Sie die Größe kennen, mit der Sie beginnen wollen - oder denken Sie kennen die Größe, ohne sicher zu sein - Sie können die MemoryStream zu Beginn so groß sein. Ebenso können Sie eine Prüfung am Ende einfügen, und wenn die Länge des Streams die gleiche Größe wie der Puffer hat (zurückgegeben von MemoryStream.GetBuffer ), dann können Sie einfach den Puffer zurückgeben. Der obige Code ist also nicht ganz optimiert, aber er ist zumindest korrekt. Er übernimmt keine Verantwortung für das Schließen des Streams - das sollte der Aufrufer tun.

Voir dieser Artikel für weitere Informationen (und eine alternative Implementierung).

883voto

Nathan Phillips Punkte 11180

Jons Antwort ist zwar richtig, aber er schreibt Code um, der bereits in CopyTo . Verwenden Sie also für .Net 4 die Lösung von Sandip, aber für frühere Versionen von .Net die Antwort von Jon. Sandips Code würde durch die Verwendung von "using" als Ausnahmen in CopyTo sind in vielen Situationen recht wahrscheinlich und würden die MemoryStream nicht entsorgt.

public static byte[] ReadFully(Stream input)
{
    using (MemoryStream ms = new MemoryStream())
    {
        input.CopyTo(ms);
        return ms.ToArray();
    }
}

133voto

Fernando Neira Punkte 3834

Ich möchte nur darauf hinweisen, dass Sie, falls Sie einen MemoryStream haben, bereits über memorystream.ToArray() dafür.

Auch wenn Sie mit Strömen unbekannter oder unterschiedlicher Subtypen zu tun haben und Sie eine MemoryStream können Sie für diese Fälle auf diese Methode zurückgreifen und für die anderen Fälle die akzeptierte Antwort verwenden, etwa so:

public static byte[] StreamToByteArray(Stream stream)
{
    if (stream is MemoryStream)
    {
        return ((MemoryStream)stream).ToArray();                
    }
    else
    {
        // Jon Skeet's accepted answer 
        return ReadFully(stream);
    }
}

76voto

Sandip Patel Punkte 747
MemoryStream ms = new MemoryStream();
file.PostedFile.InputStream.CopyTo(ms);
var byts = ms.ToArray();
ms.Dispose();

57voto

Mr. Pumpkin Punkte 5815

Nur meine paar Cent... die Praxis, die ich oft verwende, ist, die Methoden wie folgt als benutzerdefinierte Hilfe zu organisieren

public static class StreamHelpers
{
    public static byte[] ReadFully(this Stream input)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            input.CopyTo(ms);
            return ms.ToArray();
        }
    }
}

Namespace in die Konfigurationsdatei aufnehmen und überall verwenden

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X