Entrada/Salida

1. Vamos a realizar un programa que lea un fichero de texto ASCII, y lo vaya mostrando por pantalla. El esqueleto del programa se encuentra en el fichero Ej1.java. Se pide:

a) ¿Qué tipo de flujo de datos utilizaremos para leer el fichero? Añadir al programa la creación del flujo de datos adecuado (variable in), compilar y comprobar su correcto funcionamiento.

b) Podemos utilizar un flujo de procesamiento llamado BufferedReader que mantendrá un buffer de los caracteres leídos y nos permitirá leer el fichero línea a línea además de utilizar los métodos de lectura a más bajo nivel que estamos usando en el ejemplo. Consultar la documentación de la clase BufferedReader y aplicar la transformación sobre el flujo de entrada (ahora in deberá ser un objeto BufferedReader). Compilar y comprobar que sigue funcionando correctamente el método de lectura implementado.

c) Ahora vamos a cambiar la forma de leer el fichero y lo vamos a hacer línea a línea aprovechando el BufferedReader. ¿Qué método de este objeto nos permite leer líneas de la entrada? ¿Qué nos devolverá este método cuando se haya llegado al final el fichero? Implementar un bucle que vaya leyendo estas líneas y las vaya imprimiendo, hasta llegar al final del fichero. Compilar y comprobar que sigue funcionando de la misma forma.

2. En el fichero Ej2.java tenemos un programa que realizará una copia de ficheros en Java. Se pide:

a) Intentar compilar el programa y ver que errores obtenemos. Añadir la captura de las excepciones necesarias para que el programa compile (no capturar Exception en general).

b) Probar el programa copiando un fichero de texto. Comprobar que la copia se ha hecho correctamente.

c) Ahora probar a copiar el fichero notepad.exe con nuestro programa. Intentar ejecutar la copia y comprobar que falla. ¿Por qué ocurre esto? ¿Cómo podemos solucionarlo? Cambiar el tipo de flujo de datos para solucionar este problema y comprobar que la nueva versión realiza un copia correcta de notepad.exe.

3. (CHAT) Realizar un programa que lea líneas de texto de la entrada estándar y muestre por la salida estándar lo que ha introducido el usuario. Deberá funcionar como se muestra a continuación:

hola
Ha escrito "hola"

Realizaremos un módulo que pueda ser reutilizado para nuestro chat. Crearemos una clase llamada EntradaConsola en el paquete es (entrada/salida) que nos permitirá leer líneas que el usuario introduzca en la consola y pedir al usuario determinados datos. Podemos encontrar una plantilla de esta clase en es/EntradaConsola.java que deberá ser completada y probada. 

El fichero Ej3.java contiene un conductor para probar este módulo. Se pide:

a) En la clase EntradaConsola deberemos crear un flujo que lea líneas de la entrada estándar. Recordemos que esto podemos hacerlo mediante un flujo BufferedReader. Sin embargo, si nos fijamos la entrada estándar es un flujo de bytes, mientras que los objetos BufferedReader se crean a partir de flujos de caracteres. ¿Qué tendremos que hacer para poder crear BufferedReader de la entrada estándar? Aplicar el cambio en el código de la clase y comprobar que compila correctamente.
b) Añadir en readLine() de la clase EntradaConsola la llamada al método que sea necesaria para leer la línea introducida en la consola y devolverla. Capturar la excepciones necesarias, devolviendo null en caso de error. Compilar y ejecutar, comprobando que lee correctamente las líneas introducidas.

4.  (CHAT) Ahora vamos a hacer un módulo para el acceso a un fichero con información sobre los usuarios registrados. Recuerda incorporar las clases del chat creadas en sesiones anteriores para que funcione correctamente. En este caso el módulo de acceso a usuarios utilizará la excepción LoginInvalidoException. Este módulo deberá leer ficheros con el siguiente formato:

login usuario 1:password usuario 1
login usuario 2:password usuario 2
...
login usuario N:password usuario N

Podemos encontrar un fichero con los datos de los usuarios en datos\usuarios. Necesitaremos leer una serie de cadenas (login y password) separadas por caracteres de dos puntos y saltos de líneas (podemos ver estas cadenas como tokens de tipo WORD). Del acceso a este fichero se encargará la clase AccesoFicheroUsuarios de la cual podemos encontrar una plantilla en usuarios\AccesoFicheroUsuarios.java. A continuación completaremos su método leeFichero(String filename) para que realice correctamente la lectura de este formato de ficheros.

El conductor para probar este módulo se encuentra en el fichero Ej4.java. Se pide:

a) ¿Qué clase de Java nos permitirá leer este fichero de forma sencilla, obteniendo en cada lectura una de las cadenas?

b) Si queremos que el carácter ':' (constante SEPARADOR de la clase AccesoFicheroUsuarios) se utilice como separador (espacio en blanco) entre tokens , ¿qué deberemos hacer? Implementarlo en el código y probar que lee correctamente el fichero.

c) Añadir al fichero de usuarios algún usuario con espacios en blanco en su login y probar el programa, ¿qué ocurre?, ¿qué deberemos hacer para que lea toda la cadena (incluidos los espacios) como un único token? Hacer las modificaciones necesarias, y comprobar que funciona correctamente. Una vez comprobado que lee el fichero correctamente podremos eliminar las líneas System.out.println() que imprimen el login y el password.

d) Ahora nos surge un problema: ¿y si en el fichero se ha dejado un espacio al principio o al final de la cadena, o bien se han separado los dos puntos de la cadena del login o del password mediante espacios? Al reconocer los espacios como caracteres de la cadena, no será la misma cadena si está rodeada de espacios o si no lo está, cuando normalmente estos caracteres deben ser ignorados. La operación de 'limpiar' estos espacios del principio y del final de la cadena se denomina trim. ¿En qué clase deberíamos buscar esta función? Buscarla y aplicarla a las cadenas leídas del fichero. Comprobar que realmente ahora el programa ignora esos caracteres.

e) Por último, vamos a completar el método de escritura del fichero de usuarios escribeFichero(String filename, Vector lista). Queremos utilizar un flujo que nos permita escribir cadenas con el método println(), en lugar de tener que hacerlo carácter a carácter con los métodos de bajo nivel. Para ello podemos utilizar un objeto PrintWriter. Crear tanto el flujo de salida al fichero, como un objeto PrintWriter al que llamaremos out a partir de dicho flujo de salida a fichero. Ahora podemos probar el programa registrando nuevos usuarios y comprobando que se almacenan correctamente en el fichero de usuarios.