En Java 7 las clases más importantes para el tratamiento de ficheros de texto son:
- Paths y Path – Localización del fichero o nombre, no su contenido.
- Files - Operaciones con el contenido del fichero.
- StandardCharsets y Charset - Para manejar la codificación del archivo de texto.
- File.toPath – Método que permite interactuar con código antiguo a través del nuevo API java.nio
Las siguientes clases también son usadas de manera generalizada cuando trabajamos con ficheros de texto tanto en Java 7 como en versiones anteriores:
- Scanner – Permite leer ficheros de una manera sencilla.
- BufferedReader - Permite accesos de lectura línea a línea.
- BufferedWriter - Permite accesos de escritura línea a línea.
Cuando realizamos operaciones de lectura/escritura con ficheros de texto:
- Frecuentemente será buena idea utilizar buffering (por defecto el tamaño son 8K)
- Siempre tendremos que tener en cuenta el manejo de excepciones de IOException y FileNotFoundException.
java 7 : Codificación de caracteres
Para realizar operaciones sobre ficheros de texto en Java 7 tenemos que tener en cuenta que esas operaciones de lectura/escritura siempre usan una codificación de caracteres de manera implícita para traducir las cadenas de bytes en texto. Aquí es donde frecuentemente nos encontramos antes el primer problema.
Las clases FileReader y FileWriter utilizan de manera implícita la codificación de caracteres del sistema. Sin embargo, no es apropiado utilizarlo debido a los problemas que puede ocasionar usar nuestro código en diferentes sistemas operativos por ejemplo. La manera correcta es emplear aquellas clases que nos obliguen a realizar una declaración explícita de la codificación de caracteres como por ejemplo:
Java |copy code |?
1 FileInputStream fis = new FileInputStream("test.txt");2 InputStreamReader in = new InputStreamReader(fis, "UTF-8");3 4 FileOutputStream fos = new FileOutputStream("test.txt");5 OutputStreamWriter out = new OutputStreamWriter(fos, "UTF-8");6 7 Scanner scanner = new Scanner(file, "UTF-8");
java 7 + ejemplo 1
Java |copy code |?
01 package es.ivoto.cera.config;02 import java.io.BufferedReader;03 import java.io.BufferedWriter;04 import java.io.IOException;05 import java.nio.charset.Charset;06 import java.nio.charset.StandardCharsets;07 import java.nio.file.Files;08 import java.nio.file.Path;09 import java.nio.file.Paths;10 import java.util.Arrays;11 import java.util.List;12 import java.util.Scanner;13 14 public class LeerEscribirFicheroTextoJDK7 {15 16 public static void main(String... aArgs) throws IOException{17 LeerEscribirFicheroTextoJDK7 text = new LeerEscribirFicheroTextoJDK7();18 19 //Tratamiento con fichero pequeño con Java 7
20 List<String> lines = text.readSmallTextFile(FILE_NAME);21 log(lines);22 lines.add("Esta es una línea añadida desde el código.");23 text.writeSmallTextFile(lines, FILE_NAME);24 25 //Tratamiento para ficheros grandes usando buffering
26 text.readLargerTextFile(FILE_NAME);27 lines = Arrays.asList("Down to the Waterline", "Water of Love");28 text.writeLargerTextFile(OUTPUT_FILE_NAME, lines);29 }
30 31 final static String FILE_NAME = "C:\Temp\input.txt";32 final static String OUTPUT_FILE_NAME = "C:\Temp\output.txt";33 final static Charset ENCODING = StandardCharsets.UTF_8;34 35 //Para ficheros pequeños. Java 7
36 37 /**
38 Nota: el javadoc de Files.readAllLines dice que es recomendable para pequeños ficheros.
39 Pero su implementación usa buffering, por lo que también es recomendable para usarlo
40 con ficheros de texto de mayor tamaño.
41 */
42 List<String> readSmallTextFile(String aFileName) throws IOException {43 Path path = Paths.get(aFileName);44 return Files.readAllLines(path, ENCODING);45 }
46 47 void writeSmallTextFile(List<String> aLines, String aFileName) throws IOException {48 Path path = Paths.get(aFileName);49 Files.write(path, aLines, ENCODING);50 }
51 52 //Para ficheros grandes Java 7
53 54 void readLargerTextFile(String aFileName) throws IOException {55 Path path = Paths.get(aFileName);56 try (Scanner scanner = new Scanner(path, ENCODING.name())){57 while (scanner.hasNextLine()){58 //procesa cada línea del mismo modo
59 log(scanner.nextLine());60 }
61 }
62 }
63 64 void readLargerTextFileAlternate(String aFileName) throws IOException {65 Path path = Paths.get(aFileName);66 try (BufferedReader reader = Files.newBufferedReader(path, ENCODING)){67 String line = null;68 while ((line = reader.readLine()) != null) {69 //procesa cada línea del mismo modo
70 log(line);71 }
72 }
73 }
74 75 void writeLargerTextFile(String aFileName, List<String> aLines) throws IOException {76 Path path = Paths.get(aFileName);77 try (BufferedWriter writer = Files.newBufferedWriter(path, ENCODING)){78 for(String line : aLines){79 writer.write(line);80 writer.newLine();81 }
82 }
83 }
84 85 private static void log(Object aMsg){86 System.out.println(String.valueOf(aMsg));87 }
88 89 }
java 7 + : Ejemplo 2
Este ejemplo muestra el uso de Scanner con Java 7 para leer un archivo que contiene las líneas de datos estructurados. Un Scanner se utiliza para leer en cada línea, y un segundo Scanner se utiliza para analizar cada línea en un simple par nombre-valor. La clase Scanner sólo se utiliza para la lectura, no para la escritura.
Java |copy code |?
01 package es.ivoto.cera.config;02 import java.io.IOException;03 import java.nio.charset.Charset;04 import java.nio.charset.StandardCharsets;05 import java.nio.file.Path;06 import java.nio.file.Paths;07 import java.util.Scanner;08 09 /**Asumimos que el fichero está codificado en UTF-8. Java 7 +. */
10 public class LeerConScanner {11 12 public static void main(String... aArgs) throws IOException {13 LeerConScanner parser = new LeerConScanner("C:\Temp\test.txt");14 parser.processLineByLine();15 log("Done.");16 }
17 18 /**
19 Constructor.
20 @param aFileName nombre completo de un fichero existente.
21 */
22 public LeerConScanner(String aFileName){23 fFilePath = Paths.get(aFileName);24 }
25 26 27 /** Método que invoca a {@link #processLine(String)}. */
28 public final void processLineByLine() throws IOException {29 try (Scanner scanner = new Scanner(fFilePath, ENCODING.name())){30 while (scanner.hasNextLine()){31 processLine(scanner.nextLine());32 }
33 }
34 }
35 36 /**
37 Método sobreescribible para procesar las líneas de diferentes maneras.
38
39 <P>La implementación por defecto espera recibir pares de clave-valor separados por un '='.
40 Ejemplo de entradas válidas:
41 <tt>height = 178cm</tt>
42 <tt>mass = 95kg</tt>
43 <tt>disposition = "grumpy"</tt>
44 <tt>Clave = valor</tt>
45 */
46 protected void processLine(String aLine){47 Scanner scanner = new Scanner(aLine);48 scanner.useDelimiter("=");49 if (scanner.hasNext()){50 String name = scanner.next();51 String value = scanner.next();52 log("Name is : " + quote(name.trim()) + ", and Value is : " + quote(value.trim()));53 }
54 else {55 log("Línea vacía o sin la estructura esperada. No se puede procesar.");56 }
57 }
58 59 // PRIVADO
60 private final Path fFilePath;61 private final static Charset ENCODING = StandardCharsets.UTF_8;62 63 private static void log(Object aObject){64 System.out.println(String.valueOf(aObject));65 }
66 67 private String quote(String aText){68 String QUOTE = "'";69 return QUOTE + aText + QUOTE;70 }
71 }
Si ejecutas el ejemplo se obtendrá:
Text |copy code |?
1 Name is : 'height', and Value is : '167cm'2 Name is : 'mass', and Value is : '65kg'3 Name is : 'disposition', and Value is : '"grumpy"'4 Name is : 'this is the name', and Value is : 'this is the value'5 Done.
Deja tu comentario