Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
Entrada y salida (I / O)� import java.io.*� Crear un objeto File para obtener información sobre un archivo en el
drive.� Esto no crea un nuevo archivo en el disco duro.
File f = new File(“example.txt”);if (f.exists() && f.length() > 1000) {
f.delete();}
Universidad de Sonora 2
Entrada y salida (I / O)canRead() Regresa true si el archivo puede ser leídodelete() Elimina el archivo del discoexists() Regresa true si el archivo existegetName() Regresa el nombre del archivolength() Regresa el número de bytes en el archivorenameTo(file) Cambia el nombre del archivo
Universidad de Sonora 3
Leer archivos� Para leer un archivo, pasar un File al construir un Scanner.
Scanner name = new Scanner(new File(“file name”));� Ejemplo en dos líneas:
File file = new File(“mydata.txt”);Scanner input = new Scanner(file);
� Ejemplo en una línea:Scanner input = new Scanner(new File(“mydata.txt”));
Universidad de Sonora 4
Caminos (paths) de archivos� Camino absoluto: el camino es con respecto al directorio raíz “/”.
C: /Documents/smith/hw6/input/data.csv� Windows usa barras invertidas para separar carpetas.� Camino relativo: el camino es con respecto al directorio actual:
superior.datentrada/kinglear.txt../datos/star.txt
� Es relativo al directorio actual.� Por ejemplo:
Universidad de Sonora 5
Caminos (paths) de archivosScanner input = new Scanner (new File("datos/readme.txt"));
� Si el programa está en H:/hw6� Scanner buscará H:/hw6/data/readme.txt
Universidad de Sonora 6
Errores de compilador con archivosimport java.io.*; // para Fileimport java.util.*; // para Scannerpublic class ReadFile {
public static void main(String[] args){
Scanner input = new Scanner(new File(“data.txt”));String text = input.next();System.out.println(text);
}}
Universidad de Sonora 7
Errores de compilador con archivos� El programa no compila por el siguiente error:
ReadFile.java:6: unreported exceptionjava.io.FileNotFoundException;
must be caught or declared to be thrownScanner input = new Scanner(new File(“data.txt”));
^� Se necesita encerrar esa línea entre try / catch.� Es un ejemplo de una excepción marcada (checked exception).
Universidad de Sonora 8
Tokens de entrada� Token: unidad léxica separada por espacios en blanco.� Un Scanner divide el contenido de un archivo en tokens.� Si un archivo contiene lo siguiente:
� Un Scanner puede interpretar los tokens como los siguientes tipos:
Universidad de Sonora 9
Token Tipo23 int, double, String3.14 double, String“John Smith” String
Cursor de entrada� Considerar un archivo weather1.txt con el siguiente texto:
� Un Scanner ve toda entrada como un flujo de caracteres.
� Cursor de entrada: es la posición actual del Scanner. Apunta al siguiente token que se va a leer.
Universidad de Sonora 10
Consumiendo tokens� Consumir la entrada: leer de la entrada y avanzar el cursor.� Llamar a nextInt, etc. mueve el cursor después del token actual.
Universidad de Sonora 11
Ejemplo de archivos� Dado el archivo de entrada weather1.txt:
� Escribir un programa que imprima el cambio de temperatura entre cada par de días vecinos.
� 16.2 a 23.5, cambio = 7.3� 23.5 a 19.1, cambio = -4.4� 19.1 a 7.4, cambio = -11.7� 7.4 a 22.8, cambio = 15.4� Etc.
Universidad de Sonora 12
Solución// Despliega cambios en la temperatura de los datos en un archivo de
entrada.import java.io.*; // for Fileimport java.util.*; // for Scannerpublic class Temperatures {
public static void main(String[] args) throws FileNotFoundException{
Scanner input = new Scanner(new File(“weather1.txt”));double prev = input.nextDouble(); // fencepost
Universidad de Sonora 13
Soluciónfor (int i = 1; i <= 7; i++) {
double next = input.nextDouble();System.out.println(prev + “ a ” + next + “, change = ” +
(next - prev));prev = next;
}}
}
Universidad de Sonora 14
Leer un archivo entero� Suponer que se quiere que el programa funcione sin importar cuántos
números haya en el archivo.� Actualmente, si el archivo tiene más números, no se leerán.� Si el archivo tiene menos números, ¿qué pasará?� Salida de ejemplo de un archivo con solo 3 números:
Universidad de Sonora 15
Leer un archivo entero16.2 to 23.5, change = 7.323.5 to 19.1, change = -4.4Exception in thread “main”java.util.NoSuchElementExceptionat java.util.Scanner.throwFor(Scanner.java:838)at java.util.Scanner.next(Scanner.java:1347)at Temperatures.main(Temperatures.java:12)
Universidad de Sonora 16
Excepciones de Scanner� NoSuchElementException� Se leyó después del fin del archivo.� InputMismatchException� Se leyó en tipo erróneo de token (e.g. leyó “hi” como un int).
Universidad de Sonora 17
Excepciones de Scanner� Encontrando y arreglando esas excepciones:� Leer el texto de la excepción buscando las líneas del código fuente.� La primera línea que menciona el archivo; por lo general cerca del
fondo.Exception in thread “main”java.util.NoSuchElementExceptionat java.util.Scanner.throwFor(Scanner.java:838) at java.util.Scanner.next(Scanner.java:1347) at MyProgram.myMethodName(MyProgram.java:19) at MyProgram.main(MyProgram.java:6)
Universidad de Sonora 18
Pruebas de Scanner por entradas válidas
� Estos métodos de Scanner no consumen entrada; solo dan información sobre cuál será el próximo token.
� Útiles para ver qué información viene y para evitar excepciones.� Estos métodos también se pueden utilizar con un Scanner de consola.� Cuando se les llama desde la consola, a veces hacen una pausa
esperando una entrada.
Universidad de Sonora 19
hasNext() Devuelve true si hay un siguiente tokenhasNextInt() Devuelve true si hay un token siguiente y se puede leer como un inthasNextDouble() Devuelve true si hay un token siguiente y se puede leer como un double
Uso de métodos hasNext� Evitar errores de coincidencia de tipos:
Scanner console = new Scanner(System.in);System.out.print(“¿Cuál es tu edad? ”);if (console.hasNextInt()) {
int age = console.nextInt(); // funcionaSystem.out.println(“Hey, ” + age + “ es mucho”);
}else {
System.out.println(“No escribiste un entero.”);}
Universidad de Sonora 20
Uso de métodos hasNext� Evitar leer más allá del final de un archivo:
Scanner input = new Scanner(new File(“example.txt”));if (input.hasNext()) {
String token = input.next(); // funcionaSystem.out.println(“El siguiente token es ” + token);
}
Universidad de Sonora 21
Ejemplo de archivos 2� Modificar el programa de temperatura para procesar todo el archivo,
independientemente de cuántos números contenga.� Ejemplo: si se agregan los datos de un noveno día, la salida debe ser:
16.2 a 23.5, cambio = 7.323.5 a 19.1, cambio = -4.419.1 a 7.4, cambio = -11.77.4 a 22.8, cambio = 15.422.8 a 18.5, cambio = -4.318.5 a -1.8, cambio = -20.3-1.8 a 14.9, cambio = 16.714.9 a 16.1, cambio = 1.2
Universidad de Sonora 22
Solución 2// Despliega los cambios de temperatura de los datos de un archivo de
entrada.import java.io.*; // for Fileimport java.util.*; // for Scannerpublic class Temperatures {
public static void main(String[] args) throws FileNotFoundException{
Scanner input = new Scanner(new File(“weather1.txt”));double prev = input.nextDouble(); // fencepost
Universidad de Sonora 23
Solución 2while (input.hasNextDouble()) {
double next = input.nextDouble();System.out.println(prev + “ a ” + next + “, cambio = ” +
(next - prev));prev = next;
}}
}
Universidad de Sonora 24
Ejemplo de archivos 3� Modificar el programa de temperatura para manejar archivos que
contienen tokens no numéricos (saltándolos).� Por ejemplo, debe producir la misma salida que antes cuando se le da
este archivo de entrada, weather2.txt:
� Puede suponerse que el archivo comienza con un número.
Universidad de Sonora 25
Solución 3// Despliega los cambios de temperatura de los datos de un archivo de entrada.
import java.io.*; // for Fileimport java.util.*; // for Scannerpublic class Temperatures {
public static void main(String[] args) throws FileNotFoundException{
Scanner input = new Scanner(new File(“weather2.txt”));double prev = input.nextDouble(); // fencepost
Universidad de Sonora 26
Solución 3while (input.hasNext()) {
if (input.hasNextDouble()) {double next = input.nextDouble();System.out.println(prev + “ a ” + next + “, cambio = ” +
(next - prev));prev = next;
} else {input.next(); // tira los tokens no deseados
}} }
Universidad de Sonora 27
Ejemplo horas� Dado un archivo hours1.dat con el siguiente contenido:
123 Kim 12.5 8.1 7.6 3.2456 Eric 4.0 11.6 6.5 2.7 12789 Stef 8.0 8.0 8.0 8.0 7.5
� Considerar la tarea de calcular las horas trabajadas por cada persona:Kim (ID#123) trabajó 31.4 horas (7.85 horas/día)Eric (ID#456) trabajó 36.8 horas (7.36 horas/día)Stef (ID#789) trabajó 39.5 horas (7.9 horas/día)
� Intentemos resolver este problema token por token...Universidad de Sonora 28
Solución defectuosa// ¡Esta solución no funciona!import java.io.*; // para Fileimport java.util.*; // para Scannerpublic class HoursWorked {
public static void main(String[] args)throws FileNotFoundException
{Scanner input = new Scanner(new File(“hours1.dat”));
Universidad de Sonora 29
Solución defectuosawhile (input.hasNext()) {
int id = input.nextInt(); // procesa una personaString name = input.next();double totalHours = 0.0; int days = 0;while (input.hasNextDouble()) {
totalHours += input.nextDouble();days++;
}System.out.println(name + “ (ID#” + id + “) trabajó ” + totalHours +
“ horas (” + (totalHours / days) + “ hours/day)”);} } }
Universidad de Sonora 30
Solución defectuosaSusan (ID#123) worked 487.4 hours (97.48 hours/day)Exception in thread “main”java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)at java.util.Scanner.next(Scanner.java:1461)at java.util.Scanner.nextInt(Scanner.java:2091)at HoursWorked.main(HoursBad.java:9)
� El ciclo interno while toma la identificación de la siguiente persona.� Se quiere procesar los tokens, pero los saltos de línea importan porque
marcan el final de los datos de una persona.Universidad de Sonora 31
Scanner basado en líneas
Scanner input = new Scanner(new File(“file name”));while (input.hasNextLine()) {
String line = input.nextLine();process this line;
}
Universidad de Sonora 32
nextLine() Devuelve la siguiente línea completa de entrada (desde el cursor hasta \n)hasNextLine() Devuelve true si hay más líneas de entrada para leer (siempre es cierto para
la entrada de la consola)
Consumiendo líneas de entrada23 3.14 John Smith “Hello” world
45.2 19� El Scanner lee las líneas como sigue:
� Cada caracter \n se consume pero no se regresa.
Universidad de Sonora 33
Scanner sobre strings� Un Scanner puede tokenizar el contenido de un String:
Scanner name = new Scanner(String);
Universidad de Sonora 34
Scanner sobre strings� Ejemplo:
String text = “15 3.2 hello 9 27.5”;Scanner scan = new Scanner(text);int num = scan.nextInt();System.out.println(num); // 15double num2 = scan.nextDouble();System.out.println(num2); // 3.2String word = scan.next();System.out.println(word); // hello
Universidad de Sonora 35
Mezclando líneas y tokens
Universidad de Sonora 36
Archivo input.txt Salida en la consolaThe quick brown fox jumps overthe lazy dog.
La línea tiene 6 palabrasLa línea tiene 3 palabras
Mezclando líneas y tokens// Cuenta las palabras de cada línea de un archivoScanner input = new Scanner(new File(“input.txt”));while (input.hasNextLine()) {
String line = input.nextLine();Scanner lineScan = new Scanner(line);// procesa el contenido de esta líneaint count = 0;while (lineScan.hasNext()) {
String word = lineScan.next();count++;
}System.out.println(“La línea tiene ” + count + “ palabras”);
}Universidad de Sonora 37
Solución horas correcta// Procesa un archivo de empleados e imprime las horas de cada empleadoimport java.io.*; // for Fileimport java.util.*; // for Scannerpublic class Hours {
public static void main(String[] args) throws FileNotFoundException {Scanner input = new Scanner(new File(“hours.txt”));while (input.hasNextLine()) {
String line = input.nextLine();Scanner lineScan = new Scanner(line);int id = lineScan.nextInt(); // e.g. 456String name = lineScan.next(); // e.g. Eric
Universidad de Sonora 39
Solución horas correctadouble sum = 0.0;int count = 0;while (lineScan.hasNextDouble()) {
sum = sum + lineScan.nextDouble();count++;
}double average = sum / count;System.out.println(name + “ (ID#” + id + “) worked ” +
sum + “ hours (” + average + “ hours/day)”);}
}}
Universidad de Sonora 40
Salida a archivos� PrintStream: un objeto en el paquete java.io que le permite imprimir la
salida a un destino como un archivo.� Cualquier método utilizado en System.out (como print, println) funciona
en un PrintStream.� Sintaxis:
PrintStream name = new PrintStream(new File(“file name”));� Ejemplo:
PrintStream output = new PrintStream(new File(“out.txt”)); output.println(“Hello, file!”);output.println(“This is a second line of output.”);
Universidad de Sonora 41
Detalles sobre PrintStream� Si el archivo dado no existe, se crea.� Si el archivo dado ya existe, se sobrescribe.� La salida que imprime aparece en un archivo, no en la consola.� Se tiene que abrir el archivo con un editor para verlo.� No se debe abrir el mismo archivo para leer (Scanner) y escribir
(PrintStream) al mismo tiempo.� El archivo se va a sobrescribir con un archivo vacío (0 bytes).
Universidad de Sonora 42
System.out y PrintStream� El objeto de salida de la consola, System.out, es un PrintStream.
PrintStream out1 = System.out;PrintStream out2 = new PrintStream(new File(“data.txt”)); out1.println(“Hello, console!”); // va a la consolaout2.println(“Hello, file!”); // va al archivo
� Se puede guardar una referencia a System.out en una variable PrintStream.
� La impresión en la variable hace que aparezca la salida en la consola.� Se puede pasar System.out a un método como PrintStream.� Permite que un método envíe salida a la consola o un archivo.
Universidad de Sonora 43
Ejemplo con PrintStream� Modificar el programa de horas para usar un PrintStream para enviar la
salida al archivo hours_out.txt.� El programa no producirá salida de consola.� El archivo hours_out.txt se creará con el texto:
Kim (ID#123) trabajó 31.4 horas (7.85 horas/día)Eric (ID#456) trabajó 36.8 horas (7.36 horas/día)Stef (ID#789) trabajó 39.5 horas (7.9 horas/día)
Universidad de Sonora 44
Solución con PrintStream// Procesa un archivo de empleados e imprime las horas de cada empleado
import java.io.*; // for Fileimport java.util.*; // for Scannerpublic class Hours {
public static void main(String[] args) throws FileNotFoundException {Scanner input = new Scanner(new File(“hours.txt”));PrintStream out = new PrintStream(new File(“hours_out.txt”));while (input.hasNextLine()) {
String line = input.nextLine();Scanner lineScan = new Scanner(line);int id = lineScan.nextInt(); // e.g. 456String name = lineScan.next(); // e.g. Eric
Universidad de Sonora 45
Solución con PrintStreamdouble sum = 0.0;int count = 0;while (lineScan.hasNextDouble()) {
sum = sum + lineScan.nextDouble();count++;
}double average = sum / count;out.println(name + “ (ID#” + id + “) worked ” +
sum + “ hours (” + average + “ hours/day)”);}
}}
Universidad de Sonora 46
Solicitar un nombre de archivo� Se le puede pedir al usuario que indique el archivo a leer.� Si el nombre del archivo puede tener espacios, usar nextLine(), no
next().// Solicita el nombre del archivoScanner console = new Scanner(System.in);System.out.print(“Escriba el nombre del archivo de entrada: ”);String filename = console.nextLine();Scanner input = new Scanner(new File(filename));
� La clase File tiene un método exists() para revisar si el archivo existe.
Universidad de Sonora 47
Revisa si el archivo existeFile file = new File(filename);if (!file.exists()) {
// intenta otro archivo de entrada como respaldoSystem.out.print(“El archivo ” + filename + “ no existe”);file = new File(“hours1.dat”);
}
Universidad de Sonora 48
Mezclando tokens y líneas� El uso de nextLine junto con los métodos basados en tokens en el
mismo Scanner puede generar resultados no esperados.23 3.14Joe “Hello” world
45.2 19� Uno pensaría que puede leer 23 y 3.14 con nextInt y nextDouble, luego
leer Joe “Hello” world con nextLine.System.out.println(input.nextInt()); // 23System.out.println(input.nextDouble()); // 3.14System.out.println(input.nextLine()); //
Universidad de Sonora 49
Mezclando tokens y líneas� La llamada a nextLine produce un string vacío. ¿Por qué?� nextDouble no consume el fin de línea (caracter \n).
Universidad de Sonora 50
Ejemplo de línea y tokenScanner console = new Scanner(System.in);System.out.print(“Enter your age: ”);int age = console.nextInt();System.out.print(“Now enter your name: ”);String name = console.nextLine();System.out.println(name + “ is ” + age + “ years old.”);
Universidad de Sonora 51