¿Cómo convertir una secuencia en un byte en C #?

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

Llamar a la 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; } } } 

La solución más corta que conozco:

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

En .NET Framework 4 y posterior, la clase Stream tiene un método incorporado de CopyTo que puede usar.

Para las versiones anteriores del marco, la práctica función auxiliar que se tiene es:

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

Luego use uno de los métodos anteriores para copiar a un MemoryStream y llame a 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 

Edición: originalmente sugerí usar la respuesta de Jason para un Stream que admite la propiedad Length . Pero tenía un error porque suponía que Stream todos sus contenidos en una sola Read , lo que no es necesariamente cierto (no para un Socket , por ejemplo). No sé si hay un ejemplo de implementación de Stream en el BCL que sí es compatible con Length pero puede devolver los datos en fragmentos más cortos de los solicitados, pero como cualquiera puede heredar Stream este podría ser fácilmente el caso.

Probablemente sea más sencillo para la mayoría de los casos utilizar la solución general anterior, pero suponiendo que usted deseara 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, llame repetidamente a Read y mueva la posición en la que almacenará los datos.

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

Simplemente copie la clase a su solución y puede usarla en cada transmisión:

 byte[] bytes = myStream.ReadAllBytes() 

¡Funciona muy bien para todas mis transmisiones y ahorra mucho código! Por supuesto, puede modificar este método para usar algunos de los otros enfoques aquí para mejorar el rendimiento si es necesario, pero me gusta mantenerlo simple.

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

Ok, tal vez me falta algo aquí, pero esta es la forma en que lo hago:

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

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

Preguntaría, ¿por qué quieres leer una secuencia en un byte [], si deseas copiar el contenido de una secuencia, te sugiero usar MemoryStream y escribir tu secuencia de entrada en una secuencia de memoria.

si 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); } 
 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 un poco más complicada es necesaria en la s.Length superior excede Int32.MaxValue . Pero si necesita leer una secuencia tan grande en la memoria, es posible que desee pensar en un enfoque diferente para su problema.

Editar: si la transmisión no admite la propiedad Length , modifíquela utilizando la solución alternativa de 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(); 

También puede intentar simplemente leer en partes a la vez y expandir la matriz de bytes que se devuelve:

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

La matriz “bigEnough” es un poco exagerada. Claro, el buffer debe ser “grande ebough”, pero el diseño adecuado de una aplicación debe incluir transacciones y delimitadores. En esta configuración, cada transacción tendría una longitud preestablecida, por lo que la matriz anticiparía cierta cantidad de bytes e insertaría en un búfer de tamaño correcto. Los delimitadores garantizarían la integridad de la transacción y se suministrarían dentro de cada transacción. Para hacer que su aplicación sea aún mejor, puede usar 2 canales (2 sockets). Se podrían comunicar las transacciones de mensajes de control de longitud fija que incluirían información sobre el tamaño y el número de secuencia de la transacción de datos que se transferirán utilizando el canal de datos. El receptor reconocería la creación del búfer y solo entonces se enviarían los datos. Si no tiene control sobre el emisor del flujo, necesita una matriz multidimensional como buffer. Los arreglos de componentes serían lo suficientemente pequeños como para ser manejables y lo suficientemente grandes como para ser prácticos en función de su estimación de los datos esperados. La lógica del proceso buscaría los delimitadores de inicio conocidos y luego el delimitador final en las matrices de elementos subsiguientes. Una vez que se encuentra el delimitador de finalización, se creará un nuevo buffer para almacenar datos relevantes entre delimitadores y el buffer inicial tendría que ser reestructurado para permitir la eliminación de datos.

En cuanto a un código para convertir secuencia 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);