C # usando secuencias

116

Las corrientes son algo misteriosas para mí. No sé cuándo usar qué flujo y cómo usarlo. ¿Alguien puede explicarme cómo se utilizan las transmisiones?

Si lo entiendo correctamente, hay tres tipos de transmisión:

  • stream
  • read stream
  • write stream

¿Es esto correcto? Y, por ejemplo, ¿cuál es la diferencia entre ay Memorystreama FileStream?

Martijn
fuente
13
es posible que desee comprobar stackoverflow.com/questions/507747/…
Preets
3
Tome una matriz de bytes y luego cree un contenedor para ella ( Stream) que expone algunos métodos útiles, como leer, escribir y cambiar de posición. Ahora puede crear clases basadas en su almacén de respaldo (FileStream, MemoryStream) que heredan Streamy se basan en esa funcionalidad en función del almacén de respaldo en particular.
The Muffin Man

Respuestas:

80

Una secuencia es un objeto que se utiliza para transferir datos. Existe una clase de transmisión genérica System.IO.Stream, de la que se derivan todas las demás clases de transmisión en .NET. La Streamclase se ocupa de bytes.

Las clases de flujo concretas se utilizan para tratar otros tipos de datos además de los bytes. Por ejemplo:

  • La FileStreamclase se usa cuando la fuente externa es un archivo
  • MemoryStream se utiliza para almacenar datos en la memoria
  • System.Net.Sockets.NetworkStream maneja datos de red

Las transmisiones de lectura / escritura como StreamReadery StreamWriterno son transmisiones; no se derivan de System.IO.Streamellas, están diseñadas para ayudar a escribir y leer datos desde y hacia la transmisión.

Arsen Mkrtchyan
fuente
3
Entonces, si entiendo correctamente, la transmisión contiene los datos y no hace nada con ellos. ¿Las clases de "ayudante" de lector y escritor pueden manejar (manipular) los datos dentro de la secuencia?
Martijn
9
No, Stream no es un contenedor de datos, se utiliza para transferir datos, por ejemplo, FileStream transfiere datos del byte [] al archivo físico, NetworkStream transfiere byte [] por socket. Las clases de Reader Writer son clases auxiliares para escribir y leer desde la secuencia, por ejemplo, StreamReader se puede usar para leer desde la secuencia de secuencia, no el byte []. si le da FileStream como parámetro, leerá de File, si NetworkStream de socket.
Arsen Mkrtchyan
Además, StreamReader y StreamWriter son para leer y escribir secuencias de TEXTO (caracteres).
1c1cle
1
hay un buen artículo para ayudarlo a comprender MemoryStream. codeproject.com/Articles/832387/…
Jiaji Li
2
@ usuario420667. buena pregunta. En los casos de AudioStream y TemperatureStream, lo más probable es que sean BinaryStreams para el controlador asociado con el dispositivo. O bien, puede crear un CustomStream creado específicamente para la interfaz.
1c1cle
62

Para ampliar un poco otras respuestas aquí, y ayudar a explicar gran parte del código de ejemplo que verá punteado, la mayoría de las veces no lee y escribe en una transmisión directamente. Las transmisiones son un medio de bajo nivel para transferir datos.

Notará que las funciones de lectura y escritura están todas orientadas a bytes, por ejemplo WriteByte (). No hay funciones para tratar con números enteros, cadenas, etc. Esto hace que la secuencia sea de propósito general, pero menos simple de trabajar si, por ejemplo, solo desea transferir texto.

Sin embargo, .NET proporciona clases que convierten entre tipos nativos y la interfaz de flujo de bajo nivel, y transfiere los datos hacia o desde el flujo por usted. Algunas clases notables son:

StreamWriter // Badly named. Should be TextWriter.
StreamReader // Badly named. Should be TextReader.
BinaryWriter
BinaryReader

Para usarlos, primero adquiere su flujo, luego crea una de las clases anteriores y la asocia con el flujo. P.ej

MemoryStream memoryStream = new MemoryStream();
StreamWriter myStreamWriter = new StreamWriter(memoryStream);

StreamReader y StreamWriter convierten entre tipos nativos y sus representaciones de cadenas y luego transfieren las cadenas hacia y desde la secuencia como bytes. Entonces

myStreamWriter.Write(123);

escribirá "123" (tres caracteres '1', '2' y luego '3') en la secuencia. Si está tratando con archivos de texto (por ejemplo, html), StreamReader y StreamWriter son las clases que usaría.

Mientras

myBinaryWriter.Write(123);

escribirá cuatro bytes que representan el valor entero de 32 bits 123 (0x7B, 0x00, 0x00, 0x00). Si está tratando con archivos binarios o protocolos de red, BinaryReader y BinaryWriter son los que podría usar. (Si está intercambiando datos con redes u otros sistemas, debe tener en cuenta el endianismo , pero esa es otra publicación).

Tim Williams
fuente
Las clases de adaptadores StreamWriter y Reader están muy mal nombradas. Gracias por mencionar eso. Todavía me sorprende cómo se les ocurrió este nombre.
Tarik
Además, incluso las clases de escritor y lector binarios están mal nombradas.
Tarik
22

Los flujos son buenos para manejar grandes cantidades de datos. Cuando no es práctico cargar todos los datos en la memoria al mismo tiempo, puede abrirlo como una secuencia y trabajar con pequeños fragmentos.

carnívoro
fuente
1
Me encantaría ver un ejemplo de lo que acaba de decir "trabajar con pequeños trozos".
Jenna Leaf
2
Los flujos también son buenos para pequeñas cantidades de datos. Si un programador de C # desea manipular el contenido de un archivo, debe usar secuencias, independientemente de la cantidad de datos. La misma afirmación se aplica también a los flujos de red. Por supuesto, si el programador está codificando en un lenguaje de nivel inferior como C, entonces es posible escribir caracteres o bytes directamente en un disco o socket, pero incluso para una pequeña cantidad de datos, lleva mucho tiempo y es más propenso a error.
1c1cle
10

Stream es solo una abstracción (o un contenedor) sobre un physicalflujo de bytes. Esta physicalsecuencia se llama base stream. Por lo tanto, siempre hay una secuencia base sobre la que se crea una envoltura de secuencia y, por lo tanto, la envoltura recibe el nombre del tipo de secuencia base, es decir FileStream,MemoryStream etc.

La ventaja del contenedor de transmisión es que obtiene una api unificada para interactuar con transmisiones de cualquier tipo subyacente, usb, fileetc.

¿Por qué trataría los datos como flujo ? Debido a que los fragmentos de datos se cargan bajo demanda, podemos inspeccionar / procesar los datos como fragmentos en lugar de cargar todos los datos en la memoria. Así es como la mayoría de los programas tratan con archivos grandes, por ejemplo, cifrando un archivo de imagen del sistema operativo.

Anwar Husain
fuente
4

Solo hay un tipo básico de Stream . Sin embargo, en diversas circunstancias, algunos miembros lanzarán una excepción cuando se les llame porque en ese contexto la operación no estaba disponible.

Por ejemplo un MemoryStream es simplemente una forma de mover bytes dentro y fuera de una parte de la memoria. Por lo tanto, puede llamar a Leer y Escribir en él.

Por otro lado, a le FileStreampermite leer o escribir (o ambos) desde / hacia un archivo. Si realmente puede leer o escribir depende de cómo se abrió el archivo. No puede escribir en un archivo si solo lo abrió para acceso de lectura.

AnthonyWJones
fuente
3

Comenzaría leyendo sobre transmisiones en MSDN: http://msdn.microsoft.com/en-us/library/system.io.stream.aspx

Memorystream y FileStream son flujos que se utilizan para trabajar con memoria bruta y archivos respectivamente ...

Robban
fuente
Gracias por el enlace. Me encantó "Puede navegar a través del código fuente en línea, descargar la referencia para verla sin conexión y recorrer las fuentes (incluidos parches y actualizaciones) durante la depuración". Esta función ofrece un nuevo nivel de conocimiento.
David
1

Yo no llamaría a esos diferentes tipos de corrientes. La clase Stream tiene propiedades CanRead y CanWrite que le indican si se puede leer y escribir en el flujo particular.

La principal diferencia entre las diferentes clases de transmisión (como MemoryStream vs FileStream) es el almacén de respaldo, donde se leen los datos o donde se escriben. Es algo obvio por el nombre. Un MemoryStream almacena los datos solo en la memoria, un FileStream está respaldado por un archivo en el disco, un NetworkStream lee datos de la red y así sucesivamente.

Mattias S
fuente