El concepto de "flujo" se origina en el concepto de tubería en UNIX. En UNIX, una tubería es un flujo de bytes ininterrumpido que se utiliza para implementar la comunicación entre programas o procesos, o para leer y escribir dispositivos periféricos, archivos externos, etc. Protege los detalles del procesamiento de datos en el dispositivo de E/S real. Una transmisión debe tener un origen y un destino, que pueden ser ciertas áreas de la memoria de la computadora, archivos de disco o incluso una URL en Internet. La dirección del flujo es importante. Según la dirección del flujo, el flujo se puede dividir en dos categorías: flujo de entrada y flujo de salida. De hecho, la entrada/salida es para la memoria. De hecho, el origen y el destino del flujo pueden considerarse simplemente como productores y consumidores de bytes. Para el flujo de entrada, no necesita preocuparse por su origen, siempre que simplemente lea los datos del flujo y. para el flujo de entrada El flujo de salida también puede desconocer su destino y simplemente escribir datos en el flujo.
a. Corriente: conjunto de secuencias de datos ordenadas.
b Flujo de bytes: la unidad de datos más pequeña en el flujo de datos son los bytes.
c. Flujo de caracteres: la unidad de datos más pequeña en el flujo de datos es un carácter.
1. Las clases del paquete java.io corresponden a dos tipos de flujos.
Un tipo de secuencia lee o escribe directamente desde una ubicación específica (como un archivo de disco o un área de memoria). Este tipo de secuencia se denomina secuencia de nodo y otras secuencias se denominan secuencias de filtro (secuencias de empaquetado).
Filtrado de flujos: algunos flujos pueden recibir bytes de archivos y de otros lugares, y otros flujos pueden combinar bytes en tipos de datos más útiles. Un constructor que pasa una secuencia existente a otra secuencia y combina las dos secuencias. La secuencia combinada se denomina secuencia filtrada. El flujo de entrada del filtro a menudo utiliza otros flujos de entrada como fuente de entrada. Después del filtrado o procesamiento, se proporciona al usuario en forma de un nuevo flujo de entrada. Rara vez utilizamos una sola clase para crear un objeto de flujo, sino que proporcionamos la funcionalidad deseada superponiendo varios objetos (es decir, el patrón de diseño decorador).
Los flujos de entrada y salida comúnmente utilizados en Java en realidad se heredan de cuatro clases abstractas, que son:
Basado en InputStream de un solo byte, clase OutputStream (E/S orientada a bytes)
Clases de lector y escritor basadas en unidades de código Unicode de doble byte (E/S orientada a caracteres)
Una vez que se abre el flujo de entrada, el programa puede leer datos en serie del flujo de entrada. El proceso de lectura/escritura de datos del flujo de entrada es generalmente el siguiente: abrir un canal de flujo --> leer/escribir información --> cerrar el canal de flujo.
En la plataforma Java, hay dos formas de obtener el tipo de codificación de caracteres de la plataforma local:
(a) System.getProperty("archivo.codificación");
(b) Juego de caracteres cs=Charset.defaultCharset();
Todos los flujos de entrada y salida se pueden dividir en flujos de bytes (entrada, salida) y flujos de caracteres (entrada, salida). Los que procesan bytes son principalmente series (OutputStream/InputStream), y los que procesan caracteres son principalmente (Reader/Write). ) serie
2. Flujos de entrada orientados a bytes (serie InputStream). Estas clases se pueden conectar a objetos FileInputStream para proporcionar interfaces útiles:
ByteArrayInputStream: use un búfer en la memoria como InputStream
StringBufferInputStream (obsoleto en java1.1): use un objeto String como InputStream, y la implementación subyacente usa StringBuffer
FileInputStream: utilice un archivo como InputStream para implementar la operación de lectura de archivos (nombre de archivo, archivo, objeto FileDescriptor)
PipedInputStream: implementa el concepto de tubería, utilizado principalmente en subprocesos (como fuente de datos en múltiples procesos)
SequenceInputStream: combine múltiples InputStreams en un InputStream
Los flujos de salida orientados a bytes (serie OutputStream) se pueden conectar a objetos FilterOutputStream para proporcionar interfaces útiles:
ByteArrayOutputStream: crea un búfer en la memoria, almacena información en un búfer en la memoria e inicializa el tamaño del búfer (opcional)
FileOutputStream: almacena información en un archivo (nombre de archivo, archivo, FileDescriptor)
PipedOutputStream: implementa el concepto de tubería, utilizado principalmente en subprocesos (especifica el destino de los datos para subprocesos múltiples)
3. La serie correspondiente (Lector/Escritor) :
Lector: correspondiente a InputStream, adaptador InputStreamReader
Writer: corresponde a OutputStream y el adaptador es OutputStreamWriter
FileReader: Corresponde a FileOutputStream
FileWriter: corresponde a FileOurputStream
StringReader: No hay clase correspondiente
StringWriter: Corresponde a ByteArrayInputStream
CharArrayReader: Corresponde a ByteArrayOutputStream
CharArrayWriter: Corresponde a ByteArrayOutputStream
PipedReader: Corresponde a PipedInputStream
PipedWriter: Corresponde a PipedOutputStream
4. Conversión entre dos transmisiones sin restricciones ( usando la clase de adaptador)
InputStreamReader y OutputStreamReader: convierte una secuencia orientada a bytes en una secuencia orientada a caracteres.
InputStreamReader es un puente entre un flujo de bytes y un flujo de caracteres: lee bytes utilizando un juego de caracteres específico y los decodifica en caracteres. El juego de caracteres que utiliza se puede especificar por nombre o darse explícitamente, o puede aceptar el juego de caracteres predeterminado de la plataforma.
OutputStreamWriter es un puente entre el flujo de caracteres y el flujo de bytes: los caracteres que se escribirán en el flujo se pueden codificar en bytes utilizando el juego de caracteres especificado. El juego de caracteres que utiliza se puede especificar por nombre o darse explícitamente; de lo contrario, se aceptará el juego de caracteres predeterminado de la plataforma.
5. Lea datos de InputStream a través de FilterInputStream :
DataInputStream: lee datos de tipo básico (int, char, long, etc.) de la secuencia.
BufferedInputStream: utilice un búfer para evitar tener que realizar una operación de lectura real cada vez
LineNumberInputStream: registrará el número de líneas en el flujo de entrada y luego llamará a getLineNumber() y setLineNumber(int)
PushbackInputStream: rara vez se usa, generalmente se usa para el desarrollo de compiladores
Escriba en OutputStream a través de FilterOutputStream:
DataIOutputStream: los datos de tipo básico (int, char, long, etc.) se pueden enviar a la secuencia de acuerdo con el método de trasplante.
BufferedOutputStream: utilice un búfer para evitar la escritura real cada vez que envíe datos
PrintStream: produce salida formateada, donde DataOutputStream maneja el almacenamiento de datos y PrintStream maneja la visualización.
6. Cambiar el comportamiento de la transmisión.
Aunque BufferedOutputStream es una subclase de FilterOutputStream, BufferedWriter no es una subclase de FilterWriter (FilterWriter es una clase abstracta y no tiene subclases)
No existe una clase correspondiente para DataInputStream. Utilice DataInputStream a menos que utilice BufferedReader en su lugar cuando desee utilizar readLine()
BufferedReader: corresponde a BufferedInputStream
LineNumberReader: Corresponde a LineNumberInputStream
PushBackReader: Corresponde a PushbackInputStream
BufferedWrite: corresponde a BufferedOutStream
PrintWrite: corresponde a PrintStream
7. Clase independiente: RandomAccessFile
Esta clase es adecuada para archivos compuestos por registros de tamaño conocido. Además de implementar las interfaces DataInput y DataOutput (DataInputStream y DataOutputStream también implementan estas dos interfaces), RandomAccessFile es una clase completamente independiente que tiene inherentemente otros tipos de E/S. comportamientos diferentes, pueden avanzar y retroceder dentro de un archivo y se derivan directamente del Objeto.
Las operaciones de lectura y escritura en archivos se pueden completar a través del objeto RandomAccessFile.
Al generar un objeto, puede especificar la naturaleza del archivo que se abrirá: r, solo lectura; w, solo escritura;
Puede saltar directamente a la ubicación especificada en el archivo
La mayoría (pero no todas) las funciones de RandomAccessFile han sido reemplazadas por archivos de mapeo de almacenamiento nio.