Frage

Was ist die bevorzugte Methode ein Byte-Array von einem Eingangsstrom für die Erstellung von?

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 Brocken des Stroms lesen und schreiben?

War es hilfreich?

Lösung

Es hängt wirklich davon ab, ob Sie s.Length vertrauen können. Für viele Bäche, Sie wissen einfach nicht, wie viele Daten es sein wird. In solchen Fällen - und vor .NET 4 - ich Code verwenden würde:

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 , die an die Schleife in meinem Code im Grunde gleichwertig ist - schaffen die MemoryStream, Call stream.CopyTo(ms) und dann ms.ToArray() zurückzukehren. Job gemacht.

Ich sollte vielleicht erklären, warum meine Antwort ist länger als die anderen. Stream.Read garantiert nicht, dass es lesen alles, was er gefragt wird. Wenn Sie von einem Netzwerk-Stream lesen, zum Beispiel kann es ein Paket im Wert lesen und dann zurückkehren, auch wenn es bald mehr Daten sein. BinaryReader.Read halten bis zum Ende der gehen Strom oder Ihre angegebene Größe, aber immer noch die Größe, mit zu beginnen wissen müssen.

Das obige Verfahren wird halte Lesung (und Kopieren in eine MemoryStream), bis er aus Daten ausgeführt wird. Es fragt dann den MemoryStream eine Kopie der Daten in einem Array zurück. Wenn Sie wissen, die Größe, mit zu beginnen - oder denken Sie wissen, die Größe, ohne sicher zu sein - Sie MemoryStream konstruieren kann, dass Größe, um mit zu beginnen. Ebenso können Sie einen Scheck am Ende setzen, und wenn die Länge des Stroms ist die gleiche Größe wie der Puffer (zurückgegeben von MemoryStream.GetBuffer ), dann können Sie nur den Puffer zurück. So ist der obige Code ist nicht ganz optimiert, wird aber zumindest korrekt sein. Es wird keine Verantwortung für den Stream zu schließen -. Der Anrufer sollte das tun

Siehe diesen Artikel für weitere Informationen (und eine alternative Implementierung).

Andere Tipps

Während Jons Antwort richtig ist, er ist Umschreiben Code, der in CopyTo ist bereits vorhanden. Also für .Net 4 Verwendung Sandips Lösung, aber für frühere Version von .Net verwendet Jon Antwort. Sandips Code würde durch die Verwendung von „using“ verbessert werden als Ausnahmen in CopyTo sind, in vielen Situationen sehr wahrscheinlich und würde verlassen die MemoryStream nicht angeordnet ist.

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

Ich will nur darauf hinweisen, dass im Fall, dass Sie ein Memory Sie bereits memorystream.ToArray() dafür.

Auch wenn Sie mit Strömen von unbekannten oder verschiedenen Subtypen handelt und Sie eine MemoryStream empfangen können, können Sie sich auf das Verfahren für die Fälle, Relais und immer noch die akzeptierte Antwort für die anderen verwenden, wie folgt aus:

public static byte[] StreamToByteArray(Stream stream)
{
    if (stream is MemoryStream)
    {
        return ((MemoryStream)stream).ToArray();                
    }
    else
    {
        // Jon Skeet's accepted answer 
        return ReadFully(stream);
    }
}
MemoryStream ms = new MemoryStream();
file.PostedFile.InputStream.CopyTo(ms);
var byts = ms.ToArray();
ms.Dispose();

nur meine paar Cent ... die Praxis, die ich häufig verwenden, die Methoden wie diese als benutzerdefinierte Helfer zu organisieren

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

hinzufügen Namespace in die Konfigurationsdatei und verwenden Sie es überall Sie wünschen

Sie können es sogar machen schicker mit Erweiterungen:

namespace Foo
{
    public static class Extensions
    {
        public static byte[] ToByteArray(this Stream stream)
        {
            using (stream)
            {
                using (MemoryStream memStream = new MemoryStream())
                {
                     stream.CopyTo(memStream);
                     return memStream.ToArray();
                }
            }
        }
    }
}

Und dann nennen sie als reguläre Methode:

byte[] arr = someStream.ToByteArray()

Sie können einfach ToArray () -Methode von Memorystream-Klasse, für die Ex verwenden -

MemoryStream ms = (MemoryStream)dataInStream;
byte[] imageBytes = ms.ToArray();

Ich erhalte einen Fehler zur Kompilierzeit mit Bob (das heißt die des Fragestellers) Code. Stream.Length ist ein langer, während BinaryReader.ReadBytes einen ganzzahligen Parameter nimmt. In meinem Fall erwarte ich nicht mit Streams groß genug, um erfordern lange Präzision zu tun haben, so dass ich die folgende:

Stream s;
byte[] b;

if (s.Length > int.MaxValue) {
  throw new Exception("This stream is larger than the conversion algorithm can currently handle.");
}

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

Die oben ist ok ... aber Sie werden Datenverfälschungen auftreten, wenn Sie Sachen über SMTP senden (wenn Sie müssen). Ich habe auf etwas anderes verändert, die richtig Byte helfen für Byte senden: ‚

using System;
using System.IO;

        private static byte[] ReadFully(string input)
        {
            FileStream sourceFile = new FileStream(input, FileMode.Open); //Open streamer
            BinaryReader binReader = new BinaryReader(sourceFile);
            byte[] output = new byte[sourceFile.Length]; //create byte array of size file
            for (long i = 0; i < sourceFile.Length; i++)
                output[i] = binReader.ReadByte(); //read until done
            sourceFile.Close(); //dispose streamer
            binReader.Close(); //dispose reader
            return output;
        }'

Erstellen Sie eine Hilfsklasse und verweisen Sie es überall Sie wollen, es zu benutzen.

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

Falls jemand mag es, hier ist eine .NET 4+ einzige Lösung als Erweiterung Verfahren ohne unnötige Entsorgen Anruf auf dem Memory gebildet. Dies ist eine hoffnungslos triviale Optimierung, aber es ist erwähnenswert, dass ein Memorystream zu entsorgen andernfalls ist kein wirkliches Versagen.

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

In Namespace RestSharp.Extensions gibt es Verfahren ReadAsBytes. Innerhalb dieser Methode wird verwendet Memory und es ist der gleiche Code wie in einigen Beispielen auf dieser Seite, aber wenn man RestSharp verwendet das ist einfachste Weg.

using RestSharp.Extensions;
var byteArray = inputStream.ReadAsBytes();

Sie können diese Erweiterung Methode verwenden.

public static class StreamExtensions
{
    public static byte[] ToByteArray(this Stream stream)
    {
        var bytes = new List<byte>();

        int b;
        while ((b = stream.ReadByte()) != -1)
            bytes.Add((byte)b);

        return bytes.ToArray();
    }
}

Dies ist die Funktion, die ich verwende, getestet und funktionierte gut. bitte bedenken, dass ‚Input‘ nicht null und ‚input.position‘ soll auf ‚0‘ zurückgedreht wird, bevor sonst beim Lesen der Leseschleife brechen und es wird nichts lesen Array zu konvertieren.

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

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

Ich konnte es auf einer einzigen Zeile funktioniert:

byte [] byteArr= ((MemoryStream)localStream).ToArray();

als geklärte von johnnyRose wird Above-Code nur für Memory arbeiten

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top