Todo el trabajo de entrada y salida realizado en .NET Framework debe utilizar secuencias. Un flujo es una representación abstracta de un dispositivo en serie. Los dispositivos de serialización pueden almacenar datos de forma lineal y se puede acceder a ellos de la misma manera: un byte a la vez.
Hay dos tipos de transmisiones:
- Flujo de salida: al escribir datos en algún destino externo, es necesario utilizar el flujo de salida. Puede ser un archivo de disco físico, una ubicación de red, una impresora u otro programa.
- Flujo de entrada: se utiliza para leer datos en la memoria o variables accesibles por el programa. Hasta ahora, la forma más común de flujo de entrada que hemos utilizado es el teclado.
Las interfaces y clases relacionadas de la secuencia se encuentran principalmente en elSystem.IO
espacio de nombres, donde laStream
clase es una clase abstracta y tiene tres subclases importantes para diferentes objetos de acceso: laFileStream
clase representa las operaciones de archivo,MemoryStream
representa las operaciones de memoria y laBufferedStream
clase representa el procesamiento del búfer.
Clase 1.Stream
La Stream
clase abstracta contiene muchos atributos y métodos necesarios en el flujo, como se muestra en la siguiente tabla:
Estos atributos y métodos involucran todos los aspectos de la lectura y escritura del flujo. Los 4 métodos de operaciones de lectura y escritura son los siguientes:
int ReadByte();
int Read(byte[] array, int offset, int count);
void WriteByte(byte value);
void Write(byte[] array, int offset, int count);
Entre ellos ReadByte()
, los bytes leídos se convierten en números enteros y se devuelven. Si no se leen bytes, se devuelve -1
. Read()
El método devuelve el número de bytes leídos.
Por BeginRead()
, EndRead()
, BeginWrite()
y EndWrie()
por el estilo, clase Stream puede apoyar las operaciones de E / S asíncrona.
Seek()
Método significa ubicar el puntero de búsqueda en la secuencia para determinar la posición de la siguiente operación de lectura o escritura. En una secuencia de este tipo, su CanSeek
valor de atributo es true
, y su Seek()
método se puede utilizar para establecer la posición del puntero. Seek()
El método requiere dos parámetros: uno se usa para indicar el valor del movimiento del puntero de búsqueda y el otro se usa para determinar la posición de referencia del movimiento del puntero. La posición de referencia es SeekOrigin
el miembro de enumeración, que puede ser una de las siguientes tres situaciones:
- ①
SeekOrigin.Begin
(el comienzo del archivo); - ②
SeekOrigin.Current
(La posición actual del puntero en el archivo); - ③
SeekOrigin.End
(Fin de archivo).
El siguiente código muestra cómo buscar en un archivo:
aStream.Seek(200, SeekOrigin.Begin); // 从开头移到200位置
aStream.Seek(0, SeekOrigin.End); // 移到文件尾
aStream.Seek(-20, SeekOrigin.Current); // 从当前位置反向移动20
2.Clase FileStream
FileStream
Se Stream
deriva directamente de ella. FileStream
Los objetos pueden leer contenido de archivos o escribir contenido en archivos y pueden manejar bytes, caracteres, cadenas y otros tipos de datos. Este objeto también se puede utilizar para realizar una entrada / salida estándar y una salida de error estándar.
Cabe señalar que el FileStream
objeto generalmente no se usa solo, porque su aplicación está más cerca de la capa inferior. Este objeto solo puede leer y escribir bytes, por lo que al usarlo, debe convertir cadenas, números y objetos en bytes antes de que se le puedan pasar FileStream
. En vista de esto, FileStream
generalmente se empaqueta en algunas otras clases para su uso, como BinaryWriter
o TextReader
, estas clases pueden manejar estructuras de datos de alto nivel. La clase FileStream tiene muchas formas de métodos de construcción, por lo que se pueden usar diferentes métodos de construcción de acuerdo con diferentes combinaciones de los siguientes parámetros FileStream
:
- ① Nombre de archivo;
- ② Identificador de archivo: un número entero utilizado para representar el identificador de archivo;
- ③ Modo de acceso: uno de los valores de enumeración de FileMode;
- ④ Permisos de lectura / escritura: uno de los valores de enumeración de FileAccess;
- ⑤ Modo de uso compartido: uno de los valores de enumeración de FileShare;
- ⑥ Tamaño del búfer.
La Tabla 6-3, la Tabla 6-4 y la Tabla 6-5 describen respectivamente los modos de acceso a archivos, los permisos de acceso y los modos de uso compartido.
Por ejemplo, para crear un archivo y hacer que el archivo admita operaciones de lectura compartida:
FileStream fs = new FileStream(@"c:\temp\foo.txt", FileMode.Create, FileAccess.Reead);
FIleStream
Puede ser una forma síncrona o asincrónica de crear, al mismo tiempo, además de la Stream
adición de la propiedad heredada, pero también aumentar la IsAsync
propiedad. Además, el método enumerado en la siguiente tabla se agrega a esta clase: El
GetHandle()
método puede devolver un ReadFile()
identificador que se puede usar en la función del sistema operativo nativo (como en Win32 ), pero este método debe usarse con precaución. Si usa el identificador de archivo para realizar algunos cambios en el archivo subyacente y luego intenta usar el archivo FileStream
, puede dañar los datos en el archivo.
FileStream
Durante el funcionamiento de la clase, se pueden generar las siguientes excepciones:
- ① ArgumentException: la ruta es un carácter nulo
- ② ArgumentNullException: la ruta es una referencia nula
- ③ SecurityException: no hay autoridad de operación en el archivo
- ④ FileNotFoundException-archivo no encontrado
- ⑤ IOException: se han producido otros errores de E / S, como especificar un controlador incorrecto
- ⑥ DirectoryNotFoundException —— El directorio no existe
Por ejemplo, FileStream
para leer y escribir el contenido del archivo:
using System;
using System.IO;
class Test
{
static void Main(){
try {
FileStream fsw = new FileStream("test.dat", FileMode.Create, FileAccess.Write);
// Wirte some data to the stream
fsw.WriteByte(33);
fsw.Write(new byte[] {
34, 35, 36 }, 0, 3);
fsw.Close();
FileStream fsr = new FileStream("test.dat", FileMode.Open, FileAccess.Read);
Console.WriteLine(fsr.ReadByte());
Console.WriteLine(fsr.ReadByte());
Console.WriteLine(fsr.ReadByte());
Console.WriteLine(fsr.ReadByte());
} catch (Exception e) {
Console.WriteLine("Exception:" + e.ToString());
}
}
}
resultado de la operación:
3.ClaseMemoryStream
MemoryStream
De la clase también Stream
heredada, se usa la memoria en lugar del archivo para almacenar la secuencia directamente, pero se trata de algo FileStream
muy similar. MemoryStream
Los datos se almacenan en la memoria en forma de una matriz de bytes y se pueden usar para reemplazar la función de los archivos temporales en la aplicación.
Al igual que con el FileStream
mismo, MemoryStream
existen muchos métodos de construcción. Los dos siguientes se utilizan con más frecuencia:
MemoryStream();
MemoryStream(byte []);
Utilice el primer método de construcción aquí para establecer MemoryStream
que cuando los datos se escriben al final de la secuencia, se MemoryStream
pueden expandir en consecuencia. El segundo método de construcción crea una MemoryStream
nueva instancia de la clase basada en la matriz de bytes especificada , de modo que no se puede cambiar el tamaño de la secuencia creada.
Además de las Stream
propiedades heredadas, MemoryStream
se ha agregado una propiedad adicional Capacity
. Capacity
El atributo se puede utilizar para indicar el número de bytes asignados actualmente al flujo. Este atributo es muy útil cuando se utilizan flujos basados en matrices de bytes, porque este atributo puede indicar el tamaño de la matriz y el Length
atributo puede indicar el número de bytes que se utilizan actualmente.
MemoryStream
No es posible realizar métodos de lectura / escritura asíncronos porque esta función no es necesaria para la E / S de memoria. Pero el objeto puede realizar los siguientes tres métodos adicionales.
- ① ——
GetBuffer()
Devuelve una referencia a la matriz de bytes en la secuencia - ② ——Escribe
ToArray()
todo el contenido en la matriz de bytes - ③ ——Escribir
WriteTo()
el contenido de la transmisión en otra transmisión
Por ejemplo, use MemoryStream para operar en la memoria:
using System;
using System.IO;
class Test
{
static void Main(){
try {
byte[] ary = {
33, 34, 35, 36, 37 };
int b;
MemoryStream msr = new MemoryStream(ary);
MemoryStream msw = new MemoryStream();
while ((b = msr.ReadByte()) != -1) {
msw.WriteByte((byte)(b + 3));
}
byte[] result = msw.ToArray();
foreach (byte bt in result)
Console.WriteLine(bt);
} catch (Exception e) {
Console.WriteLine("Exception:" + e.ToString());
}
}
}
resultado de la operación:
4.BufferedStrea 类
BufferedStream
Puede mejorar la eficiencia de ejecución de las operaciones de lectura y escritura, porque esta clase puede almacenar datos en caché en la memoria, reduciendo así el número de llamadas al sistema operativo. BufferedStream
No se puede usar solo, sino que se debe empaquetar en algunos otros tipos de flujos, especialmente los tipos BinaryWriter
y BinaryReader
tipos que se describen a continuación . Además, también es común almacenar en caché y envolver el flujo de red (NetworkStream). Para la operación de BinaryStream
llamada Flush()
, el contenido almacenado en caché se puede escribir en la secuencia.