¿Cuál es el método preferido para crear una matriz de bytes a partir de una secuencia de entrada?
Aquí está mi solución actual con .NET 3.5.
Stream s;
byte[] b;
using (BinaryReader br = new BinaryReader(s))
{
b = br.ReadBytes((int)s.Length);
}
¿Sigue siendo una mejor idea leer y escribir fragmentos de la secuencia?
c#
.net-3.5
inputstream
Beto
fuente
fuente
Respuestas:
Realmente depende de si puedes confiar o no
s.Length
. Para muchas transmisiones, simplemente no sabes cuántos datos habrá. En tales casos, y antes de .NET 4, usaría un código como este:Con .NET 4 y superior, usaría
Stream.CopyTo
, que es básicamente equivalente al bucle en mi código: crearMemoryStream
, llamarstream.CopyTo(ms)
y luego regresarms.ToArray()
. Trabajo hecho.Quizás debería explicar por qué mi respuesta es más larga que las otras.
Stream.Read
no garantiza que leerá todo lo que se le solicite. Si está leyendo desde una transmisión de red, por ejemplo, puede leer el valor de un paquete y luego regresar, incluso si habrá más datos pronto.BinaryReader.Read
continuará hasta el final de la transmisión o el tamaño especificado, pero aún debe saber el tamaño para comenzar.El método anterior seguirá leyendo (y copiando en a
MemoryStream
) hasta que se quede sin datos. Luego le pideMemoryStream
que devuelva una copia de los datos en una matriz. Si conoce el tamaño para comenzar, o cree que conoce el tamaño, sin estar seguro, puede construir elMemoryStream
tamaño para comenzar. Del mismo modo, puede marcar al final, y si la longitud de la secuencia es del mismo tamaño que el búfer (devuelto porMemoryStream.GetBuffer
), puede devolver el búfer. Entonces, el código anterior no está optimizado, pero al menos será correcto. No asume ninguna responsabilidad por cerrar la transmisión; la persona que llama debe hacerlo.Consulte este artículo para obtener más información (y una implementación alternativa).
fuente
16*1024
específicamente?Si bien la respuesta de Jon es correcta, está reescribiendo el código que ya existe
CopyTo
. Entonces, para .Net 4 use la solución de Sandip, pero para la versión anterior de .Net use la respuesta de Jon. El código de Sandip se mejoraría mediante el uso de "usar", ya que las excepcionesCopyTo
son, en muchas situaciones, bastante probables y dejarían loMemoryStream
no dispuesto.fuente
input
ya hay unMemorySteam
cortocircuito. Sé que sería estúpido por parte de la persona que llama pasar unMemoryStream
pero ...MemoryStream
pregunta, entonces si la optimización tiene sentido en su contexto es la comparación del tiempo necesario para realizar millones de conversiones de tipos con el tiempo necesario para copiar la que estáMemoryStream
en otraMemoryStream
.Solo quiero señalar que en caso de que tenga un MemoryStream que ya tiene
memorystream.ToArray()
para eso.Además, si se trata de secuencias de subtipos desconocidos o diferentes y puede recibir un
MemoryStream
, puede transmitir dicho método para esos casos y aún usar la respuesta aceptada para los demás, como esta:fuente
MemoryStream
s. Por supuesto, el ejemplo también es obviamente incompleto, en cuanto a cómo está utilizando una variable no inicializada.stream.Seek(1L, SeekOrigin.Begin)
, antes de invocar con facilidad, si la secuencia es una secuencia de memoria, obtendrá 1 byte más que si se trata de cualquier otra secuencia. Si la persona que llama espera leer desde donde está la posición actual hasta el final de la transmisión, entonces no debe usarCopyTo
oToArray()
; En la mayoría de los casos, esto no será un problema, pero si la persona que llama no sabe acerca de este comportamiento peculiar, se confundirá.fuente
solo mi par de centavos ... la práctica que uso a menudo es organizar métodos como este como ayuda personalizada
agregue espacio de nombres al archivo de configuración y úselo donde desee
fuente
CopyTo
versiones posteriores, ya que no estaba disponibleStream
hasta 4.0.Simplemente puede usar el método ToArray () de la clase MemoryStream, por ejemplo
fuente
Incluso puedes hacerlo más elegante con extensiones:
Y luego llámalo como un método regular:
fuente
Recibo un error de tiempo de compilación con el código de Bob (es decir, el interrogador). Stream.Length es largo mientras que BinaryReader.ReadBytes toma un parámetro entero. En mi caso, no espero tratar con Streams lo suficientemente grandes como para requerir una precisión larga, por lo que utilizo lo siguiente:
fuente
En caso de que a alguien le guste, aquí hay una solución única .NET 4+ formada como un método de extensión sin la innecesaria llamada Dispose en MemoryStream. Esta es una optimización irremediablemente trivial, pero vale la pena señalar que no eliminar un MemoryStream no es una falla real.
fuente
El anterior está bien ... pero encontrará daños en los datos cuando envíe cosas a través de SMTP (si es necesario). He cambiado a otra cosa que ayudará a enviar correctamente byte por byte: '
fuente
Cree una clase auxiliar y haga referencia a ella en cualquier lugar donde desee usarla.
fuente
En el espacio de nombres RestSharp.Extensions hay un método ReadAsBytes. Dentro de este método se usa MemoryStream y hay el mismo código que en algunos ejemplos de esta página, pero cuando usa RestSharp, esta es la forma más fácil.
fuente
Puedes usar este método de extensión.
fuente
Esta es la función que estoy usando, probé y funcionó bien. tenga en cuenta que 'input' no debe ser nulo y 'input.position' debe restablecerse a '0' antes de leer, de lo contrario se romperá el ciclo de lectura y nada se leerá para convertirlo en matriz.
fuente
fuente
pude hacerlo funcionar en una sola línea:
según lo aclarado por johnnyRose , el código anterior solo funcionará para MemoryStream
fuente
localStream
no es unMemoryStream
? Este código fallará.localStream
a unaMemoryStream
, perolocalStream
es no unaMemoryStream
, que va a fallar. Este código se compilará bien, pero podría fallar en tiempo de ejecución, dependiendo del tipo real delocalStream
. No siempre puede emitir arbitrariamente un tipo base a un tipo secundario; Lea más aquí . Este es otro buen ejemplo que explica por qué no siempre puedes hacer esto.