Pregunta

    

Esta pregunta ya tiene una respuesta aquí:

         

¿Hay una manera simple o método para convertir un Stream en un byte[] en C #?

¿Fue útil?

Solución

Llamada siguiente función como

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

Función:

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

Otros consejos

La solución más corta sé:

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

En .NET Framework 4 y más tarde, la clase Stream tiene incorporado un método CopyTo que puede utilizar.

En versiones anteriores de la estructura, la función de ayuda es útil tener:

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

A continuación, utilice uno de los métodos anteriores para copiar en un MemoryStream y llame GetBuffer en él:

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

Editar inicialmente me sugirió el uso de respuesta de Jason como un Stream que admite la propiedad Length. Pero tenía un defecto, ya que supone que el Stream volvería todo su contenido en una sola Read, lo cual no es necesariamente cierto (no para un Socket, por ejemplo.) No sé si hay un ejemplo de una aplicación Stream en el BCL que hace de soporte Length pero podría devolver los datos en fragmentos más cortos que usted solicita, pero como cualquier persona puede heredar Stream esto podría fácilmente ser el caso.

Es probable que sea más fácil para la mayoría de los casos a utilizar la solución general anterior, pero suponiendo que se quiere leer directamente en una matriz que es bigEnough:

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

Es decir, llamar repetidamente Read y mover la posición que va a almacenar los datos en.

    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

Yo uso esta clase de extensión:

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

Sólo tienes que copiar la clase a su solución y se puede usar en todas las corrientes:

byte[] bytes = myStream.ReadAllBytes()

funciona muy bien para todos mis emisiones y ahorra un montón de código! Por supuesto, puede modificar este método a utilizar algunos de los otros enfoques aquí para mejorar el rendimiento si es necesario, pero me gusta que sea sencillo.

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

Ok, tal vez estoy perdiendo algo, pero esta es la manera de hacerlo:

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

si usted publica un archivo desde un dispositivo móvil u otro

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

técnica rápida y sucia:

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

Prueba:

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

Me gustaría preguntar, ¿por qué quiere leer una secuencia en un byte [], si se desean copiar el contenido de un arroyo, puedo sugerir el uso de MemoryStream y escribir su flujo de entrada en una secuencia de 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 solución ligeramente más complicado es NECESARIO es s.Length excede Int32.MaxValue. Pero si usted necesita leer una corriente tan grande en la memoria, es posible que desee pensar en un enfoque diferente a su problema.

Editar: Si el flujo no admite la propiedad Length, modificar el uso de Earwicker solución .

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

También puede probar simplemente leer en partes a la vez y la expansión de la matriz de bytes de ser devuelto:

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" matriz es un poco de un tramo. Seguro, tampón tiene que ser "grande ebough" pero el diseño adecuado de una aplicación debe incluir las transacciones y delimitadores. En esta configuración cada transacción tendría una longitud preestablecida de este modo la matriz de anticiparía cierto número de bytes y la inserta en tampón de tamaño correcto. Los delimitadores asegurarían integridad de la transacción y se suministra dentro de cada transacción. Para realizar su solicitud, incluso mejor, se podría utilizar 2 canales (2 enchufes). Uno podría comunicar las transacciones de mensajes de control de longitud fija que incluirían información sobre el tamaño y número de secuencia de transacción de datos a ser transferidos utilizando el canal de datos. Receptor reconocería la creación de amortiguación y sólo entonces sería enviado datos. Si no tiene ningún control sobre el remitente corriente de lo que necesita matriz multidimensional como un amortiguador. matrices de componentes serían lo suficientemente pequeño como para ser manejable y lo suficientemente grande como para ser práctico basado en la estimación de los datos esperados. lógica de proceso buscaría delimitadores de inicio y conocidos delimitador luego termina en conjuntos de elementos posteriores. Una vez que termina delimitador se encuentra, nuevo buffer se creó para almacenar datos relevantes entre los delimitadores y el tampón inicial tendría que ser reestructurado para permitir la eliminación de datos.

En la medida como un código para convertir corriente en matriz de bytes es uno a continuación.

Stream s = yourStream;
int streamEnd = Convert.ToInt32(s.Length);
byte[] buffer = new byte[streamEnd];
s.Read(buffer, 0, streamEnd);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top