Domanda

    

Questa domanda ha già una risposta qui:

    
            
  •              Creazione di un array di byte da un flusso                                      16 risposte                          
  •     
    

C'è un modo semplice o un metodo per convertire un Stream in un byte[] in C #?

È stato utile?

Soluzione

chiamata successiva funzione come

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

funzione:

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

Altri suggerimenti

La soluzione più breve lo so:

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

In .NET Framework 4 e versioni successive, la classe Stream ha un built-in metodo CopyTo che è possibile utilizzare.

Per le versioni precedenti del quadro, la funzione di supporto comodo avere è:

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

Quindi utilizzare uno dei metodi di cui sopra per copiare ad un MemoryStream e chiamare GetBuffer su di esso:

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

Modifica in origine ho suggerito usando la risposta di Jason per un Stream che supporta la proprietà Length. Ma aveva un difetto perché si presume che il Stream sarebbe tornato tutto il suo contenuto in un unico Read, che non è necessariamente vero (non per un Socket, per esempio.) Non so se v'è un esempio di implementazione Stream nel BCL che fa il supporto Length ma potrebbe restituire i dati in blocchi più brevi di quanto si richiede, ma come chiunque può ereditare Stream questo potrebbe facilmente essere il caso.

E 'probabilmente più semplice per la maggior parte dei casi a utilizzare la soluzione generale di cui sopra, ma supponendo che si voleva leggere direttamente in un array che è bigEnough:

byte[] b = new byte[bigEnough];
int r, offset;
while ((r = input.Read(b, offset, b.Length - offset)) > 0)
    offset += r;

Cioè, più volte chiamare Read e spostare la posizione vi sarà la memorizzazione dei dati a.

    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

Io uso questa classe di estensione:

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

Basta copiare la classe alla soluzione e si può utilizzare su ogni flusso:

byte[] bytes = myStream.ReadAllBytes()

funziona alla grande per tutti i miei corsi d'acqua e consente di risparmiare un sacco di codice! Naturalmente è possibile modificare questo metodo da utilizzare alcuni degli altri approcci qui per migliorare le prestazioni in caso di necessità, ma mi piace mantenere le cose semplici.

Byte[] Content = new BinaryReader(file.InputStream).ReadBytes(file.ContentLength);

Ok, forse sto perdendo qualcosa, ma questo è il modo in cui lo faccio:

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

se pubblichi un file da un dispositivo mobile o altro

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

tecnica veloce e sporco:

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

Prova:

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

Vorrei chiedere, perché vuoi per leggere un flusso in un byte [], se si desiderano copiare il contenuto di un corso d'acqua, mi permetto di suggerire utilizzando MemoryStream e scrivere il vostro flusso di input in un flusso di memoria.

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

Una soluzione leggermente più complicato è necesary è s.Length supera Int32.MaxValue. Ma se avete bisogno di leggere un flusso che di grandi dimensioni in memoria, si potrebbe desiderare di pensare a un approccio diverso al problema.

Edit: Se il flusso non supporta la proprietà Length, modificare usando di Earwicker soluzione .

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

Si potrebbe anche provare solo la lettura di parti in un momento e in espansione l'array di byte da restituire:

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

"bigEnough" array è un po 'un tratto. Certo, il tampone ha bisogno di essere "grande ebough", ma una corretta progettazione di un'applicazione dovrebbe includere transazioni e delimitatori. In questa configurazione, ogni transazione avrebbe una lunghezza predeterminata così la matrice sarebbe anticipare certo numero di byte e inserirlo nel buffer di dimensioni corrette. Delimitatori garantirebbe integrità transazione e dovrebbero essere forniti in ciascuno transazione. Per rendere l'applicazione ancora meglio, è possibile utilizzare 2 canali (2 prese). Si potrebbe comunicare transazioni dei messaggi di controllo a lunghezza fissa che comprenda informazioni sulle dimensioni e il numero di sequenza di transazioni di dati da trasferire tramite canale dati. Ricevitore riconoscerebbe la creazione di buffer e solo allora i dati sarebbe stato inviato. Se si dispone di alcun controllo sul torrente mittente del necessario array multidimensionale come un buffer. array componenti sarebbero abbastanza piccolo da essere gestibile e abbastanza grande per essere pratico in base alla stima dei dati previsti. logica di processo cercherebbe noti delimitatori di inizio ed delimitatore poi finire nelle successive array elemento. Una volta che termina delimitatore viene trovato, nuovo buffer verrebbe creata per archiviare i dati rilevanti tra delimitatori e tampone iniziale avrebbe dovuto essere ristrutturato per consentire lo smaltimento dei dati.

Per quanto riguarda un codice per la conversione in flusso di byte è quella sottostante.

Stream s = yourStream;
int streamEnd = Convert.ToInt32(s.Length);
byte[] buffer = new byte[streamEnd];
s.Read(buffer, 0, streamEnd);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top