Download Flujos (streams)

Document related concepts
no text concepts found
Transcript
Flujos (streams)
Programación
Nadjet Bouayad-Agha
Licenciatura Lingüística y Nuevas Tecnologias
2007
Agenda
•
•
•
•
Java e argumentos de entrada: args.zip
Como leer e escribir datos de/a los flujos estándares.
¿Qué es un flujo?
Como leer cualquier tipo de datos del flujo de entrada
estándar.
• Como leer un fichero e escribir a un fichero.
Leer e escribir datos
• Leemos e escribimos datos del flujo estándar de
entrada/salida:
System.out.println(“Hello”);
System.in.read();
• Hasta ahora, para leer datos, utilizamos el paquete
TextIO:
TextIO.getlnChar();
Flujos estándares
• Los flujos estándar de entrada y salida siempre están
abiertos mientras se ejecuta el programa, listos para
proporcionar datos (entrada) o para acceptar datos (salida).
• Por defecto, el flujo estándar de entrada es el teclado.
Referimos al flujo estándar de entrada con System.in
• Por defecto, el flujo estándar de salida es la pantalla.
Referimos al flujo estándar de salida con System.out
int System.in.read()
• Lee un código ascii entre 0 y 255 (un byte) y lo pone en un int.
System.out.print(“Introduzca caracter: );
char c = (char)System.in.read();
System.out.println(“\nIntroduciste un: “ + c);
ReadCharacter.java
• Podemos leer del flujo de entrada estándar tantos caracteres
como queremos, hasta encontrar eof (End Of File). Al encontrar
eof, System.in.read() devuelve -1.
• Podemos simular eof dentro de una ventana cmd Windows
(dentro de Netbeans, no podemos). Para esto, entramos
Control-Z (en una nueva linea):
ReadCharacters1.java
int System.in.read()
Importante 1: Para compilar ReadCharacters1.java dentro de la ventana cmd, podemos entrar:
javac ReadCharacters.java
Si dice que no reconoce el comando, esto probablemente quiere decir que no está especificado donde encontrar el compilador de Java.
Hay que añadir el path de donde esta javac. Para mirar el path, entrar “path” en la ventana cmd. Para añadir un nuevo path al path
actual, ponemos: PATH=%PATH%;...
Importante 2: La JVM tiene que saber donde están ubicadas las clases. Por eso, antes de ejecutar el programa bajo cmd, hay que
especificar el classpath: set classpath=. (es decir las clases se encuentran en la carpeta actual). Si no, la JVM no encontrará las
clases y se imprimirá el siguiente mensaje:
Exception in thread "main" java.lang.NoClassDefFoundError
Excepciones
• El método System.in.read() está definido como:
int read() throws IOException
Es decir que su utilización puede provocar una excepción de tipo
IO (Input/Output).
• Tenemos la obligación de hacer algo con esta excepción. Si no,
occurren errores de compilación: ReadCharacters0.java
Excepciones
• Posibilidad 1: Lanzar esta excepción otra vez fuera del main:
public static void main(String[ ] args) throws IOException
ReadCharacters1.java
• Posibilidad 2: Atrapar la excepción con una instrucción try-catch
y procesarla in situ, imprimiendo un mensaje inteligible:
ReadCharacters2.java
• Para más información sobre Excepciones y su manejo, ver las
explicaciones en: exceptions.ppt
Redirigir los flujos estándares
• Podemos redirigir los flujos estándares de entrada y salida
para leer o escribir a un fichero. Por ejemplo, podemos entrar
desde la línea de comandos (cmd):
– java ReadCharacters1 < inputReadCharacters.txt
System.in es el flujo abierto desde el fichero inputReadCharacters.txt
Cada instrucción System.in.read() lee un carácter de este fichero.
ReadCharacters1 lee el contenido de inputReadCharacters.txt, hasta
alcanzar eof. En este caso, no hace falta Control-Z, eof occurre cuando
se alcanza el final del fichero!
– java ReadCharacters1 > outputReadCharacters.txt
System.out es el flujo abierto al fichero outputReadCharacters.txt
Cada instrucción System.out.println escribe a este fichero
Si el fichero existe, el comando lo sobre-escribe (overwrite).
Redirigir los flujos estándares
– java ReadCharacters1 >> outputReadCharacters.txt
La instrucción >> redirige el flujo estándar de salida, pero sin sobre-escribir el
fichero si ya existe
– java ReadCharacters1 < inputReadCharacters.txt > outputReadCharacters.txt
Lee de inputReadCharacters.txt y escribe a outputReadCharacters.txt
Flujo (stream)
•
•
•
Un flujo, o stream, es una conexión entre un programa y una fuente o
destino de datos.
Un flujo de entrada maneja los datos que fluyen al programa
Un flujo de salida maneja los datos que fluyen del programa
•
•
En la figura, es un trozo de información
Ejemplo de aparatos de IO: conexión a internet, teclado, ratón,
pantalla, impresora, disco duro (es I y O, depende de la aplicación).
• System.in y System.out son streams creados automaticamente
cuando se ejecuta un programa Java.
(img source Kjell)
Tipo de datos transmitidos por los flujos
• Con System.in.read( ), los trozos de información transmitidos del
teclado al programa son de tipo byte.
• Problema: ¿Como podemos leer otros datos como int o double,
que no caben en un byte? ¿Como podemos leer caracteres otros
que ASCII (e.g., Unicode)?
• Solución: Necesitamos utilizar flujos de caracteres.
Nota: Tecnicamente, read() es un método asociado con la variable in, que es una
variable de clase de System. La variable in es de tipo InputStream, que permite
manejar flujos de entrada como bytes.
Flujos de bytes vs de caracteres
• Existen dos tipos de flujos, flujos de bytes (byte streams) y
flujos de caracteres (carácter streams).
• Los flujos de caracteres se usan para manipular datos legibles
por humanos (por ejemplo un fichero .txt).
• Los flujos de bytes se usan para manipular datos binarios,
legibles solo por la maquina (por ejemplo un fichero .exe)
Flujos (Streams)
import java.io.*;
1. Abrir el stream
2. Usar el stream (leer, escribir)
3. Cerrar el stream
¿Como leer una línea entera
desde el flujo de entrada estándar?
•
•
Código completo: SystemIn.java
Se necesitan 3 flujos:
–
System.in de tipo InputStream lee Bytes desde el flujo de
entrada estándar .
–
InputStreamReader lee Bytes y les descodifica como
carácteres.
–
BufferedReader lee caracteres y les agrupa en líneas.
(source Kjell)
¿Como leer una línea entera
desde el flujo de entrada estándar?
• Flujo de carácteres BufferedReader:
Abre un flujo que lee desde un flujo de entrada de caracteres,
agrupa los caracteres a leer en un buffer (una zona de
memoria que sirve de tapón mientras se están transmitiendo
los datos) , así permitiendo leer lineas enteras:
public String readLine() throws IOException
• Creamos un flujo BufferedReader a partir de un flujo de caracteres:
public BufferedReader(Reader in)
¿Como leer números desde
el flujo de entrada estándar?
• Hacemos como en en SystemIn.java, leemos lineas de String,
pero en bucle:
– Leer 10 números desde el flujo estándar y sumarlos:
SumarDiez.java
– Leer N números desde el flujo estándar y sumarlos (Ctrl-Z es
eof, que para String es null):
Sumar.java
• Convertimos el String a int con:
int Integer.parseInt(String cadena)
• Antes de convertir la cadena a un entero, tenemos que eliminar la
nueva línea (\n). Para eso sirve trim(). Si no, la conversión
fracasa y se produce una excepción:
java.lang.NumberFormatException
Como leer un fichero
• Para leer cualquier tipo de datos desde un archivo, procedemos
en dos etapas: crear un objeto de tipo FileReader y luego un
objeto de tipo BufferedReader.
• FileReader:
public FileReader(String fileName) throws FileNotFoundException
Establece un flujo de entrada para leer caracteres desde una fuente
externa (fichero). Los métodos read de FileReader solo leen un
carácter o un trozo de un array de carácter.
• Podemos leer líneas enteras de carácteres abriendo un flujo de
tipo BufferedReader a partir de un flujo de tipo FileReader.
• Ejemplo: InStream.java
Como escribir a un fichero
• FileWriter:
public FileWriter(String fileName) throws IOException
Abre un flujo de salida para escribir caracteres. Uno de sus métodos
write (el de su super-clase Writer), puede imprimir un String:
public void write(String str) throws IOException
• Ejemplo: OutStream.java