Manejo de Archivos en Java
-
Upload
diego-tipan -
Category
Documents
-
view
63 -
download
0
description
Transcript of Manejo de Archivos en Java
-
1. Archivos
La mayora de los desarrolladores Java no requieren del manejo de archivos en sus
labores diarias, sin embargo es esencial ya que muchas de las operaciones de I/O
(Lectura y Escritura de informacin) que involucran archivos tienen mucho que ver
con el rendimiento de algunas aplicaciones.
Procesos de migracin de aplicaciones, integraciones con sistemas legados, carga
de archivos en aplicaciones web, procesos batch, procesos de facturacin
electrnica, etc. son algunas de las aplicaciones en las que se requiere del manejo
de archivos.
Java dentro de su paquete conocido como NIO provee un conjunto de clases para
trabajar con archivos y procesos de I/O en general.
Con el JDK 7 se incluyen un nuevo conjunto de clases en el paquete NIO2 cuyo
enfoque es hacer ms sencillo desde el punto de vista del desarrollo muchas de las
operaciones de I/O, entre ellas la manipulacin de archivos.
Si bien Java desde su inicio se concibi de manera independiente de la plataforma,
muchas de las operaciones que se realizan con archivos si son dependientes de la
plataforma, operaciones sobre symbolic links o vnculos simblicos existen solo en
plataformas Unix es un ejemplo de esta dependencia.
Durante esta lectura revisaremos las clases necesarias para el manejo de archivos
tanto con la versin inicial de Java NIO y NIO2
1.1. Clases para el manejo de Archivos
1. File: Es una representacin abstracta de un archivo o directorio. Esta clase no se
utiliza para escribir o leer datos, si no para trabajar a alto nivel; es decir para crear, buscar, eliminar archivos y para trabajar con directorios y rutas.
2. FileReader: Esta clase se usa para leer caracteres de un archivo. Tiene un
mtodo read() de bajo nivel, el cual se puede utilizar para leer un simple carcter,
un flujo entero de caracteres, o un nmero especfico de caracteres.
3. BufferedReader: Esta clase se utiliza para hacer ms eficientes las
operaciones de lectura cuando se trata de grandes cantidades de informacin,
permite almacenar los datos en un buffer. De este modo cada vez que se necesite
obtener la informacin, se obtendr desde el buffer minimizando as los accesos a
disco.
4. FileWriter: Esta clase se usa para escribir caracteres en un archivo. Posee el
mtodo write() que permite escribir caracteres o Strings a un archivo.
5. BufferedWriter: Se utiliza para hacer ms eficiente la escritura de grandes
cantidades de informacin a un archivo de una vez, minimizando el nmero de
operaciones de escritura. Tambin provee el mtodo writeLine(), el cual aade los
caracteres de salto de lnea correspondientes a la plataforma en la que se ejecuta.
6. PrintWriter: Envuelve las clases FileWriter y BufferedWriter. Aade varios
mtodos como format(), printf() y append() que brindan mayor flexibilidad y poder.
1.2. Clases para el manejo de Archivos NIO2
-
1. Path: Se puede considerar de una actualizacin sobre la clase File.
La clase Path es una referencia programtica del mismo concepto relacionado
dentro de un sistema de archivos, un Path se refiere a una ruta dentro un esquema
jerrquico ya sea de un archivo o de un directorio.
2. Paths: Se trata de una clase utilitaria que permite obtener un Path a partir de un
String o de una URI.
3. Files: Se trata de una clase utilitaria que permite realizar operaciones sobre
archivos y directorios.
2. STREAMS
La habilidad de escribir y leer datos de algn recurso o medio y de utilizarla para
producir una salida es una caracterstica muy comn en las aplicaciones
empresariales. A esta interaccin que tiene un programa con el resto se la conoce
como Input/Output (IO)
Tomando en cuenta que un computador puede conectarse a diferentes tipos de
dispositivos de entrada y salida, se hizo necesario definir una forma de abstraer los
diferentes tipos de informacin que se intercambia entre el computador y los
dispositivos, a este flujo de informacin se le conoce con el nombre de Streams.
Las clases utilizadas para realizar las diferentes operaciones de I/O se encuentran
ubicadas en el paquete java.io.*, que contiene todas las clases Streams que
soportan los algoritmos de escritura - lectura. Estas clases estn dividas en dos
grupos jerrquicos, basados en el tipo de dato y son las siguientes:
Character Streams
Byte Streams
2.1 Character Streams Son especializados para lectura y escritura de caracteres de datos entendibles por
el usuario (humano). Las clases principales o superclases para el manejo de
caracteres son Reader y Writer, a partir de las cuales existen muchas
generalizaciones.
Es importante aclarar que los caracteres son almacenados en la computadora como
valores Unicode de 16 bits, por lo cual la mayora de programas deberan utilizar
los character streams para leer o escribir informacin textual, ya que estos
pueden manejar cualquier carcter unicode.
2.2 Byte Streams
-
Son especializados para lectura y escritura de datos en formato de mquina, debido
que son almacenados como 8 bytes. Las clases principales o superclases para el
manejo de bytes son InputStream y OutputStream. Estos streams son
especializados para leer o escribir datos binarios como sonidos o imgenes.
Dentro de las generalizaciones de Byte Streams, se tiene a las
clases ObjectInputStream y ObjectOutputStream que son usadas para la
serializacin de objetos.
Cabe destacar que los APIS utilizados para los Character Streams y Byte
Streams son similares variando solamente el tipo de dato.
2.3. Clasificacin Streams
Entre los tipos de Streams de acuerdo al mbito, entre los ms comunes podemos
mencionar los siguientes:
mbito Streams Descripcin
Memoria CharArrayReader, CharArrayWriter ByteArrayInputStream, ByteArrayOutputStream StringReader, StringWriter
Usados para leer y escribir a memoria ya sea utilizando caracteres o bytes como datos.
Archivos FileReader, FileWriter FileInputStream, FileOutputStream
Usados para leer de un archivo o escribir a uno sobre un sistema de archivos nativo. (NTFS, EXT3).
Serializacin Objetos ObjectInputStream, ObjectOutputStream Usado para serializar objetos
Filtrado FilterReader, FilterWriter FIlterInputStream, FilterOutputStream
Usados para filtrar los datos de un stream ya sea para leer o escribir al mismo.
3. Manejo de Archivos - La clase Path Previa a la creacin de un archivo, es necesario crear una referencia dentro del
sistema de archivos del sistema operativo correspondiente, como se mencion la
clase File y la clase Path son las que permiten este manejo.
Veamos a continuacin como se lo realiza en cdigo:
Utilizando la clase File
import java.io.File;
public class ManejadorDeArchivos{
File file= new File("c:\\ejemplos\\archivo1.txt"); }
Utilizando la clase Path
import java.nio.file.Path;
import java.nio.file.Paths;
public class ManejadorDeArchivos{ Path path = Paths.get("c:\\ejemplos\\archivo1.txt"); }
-
En ambos casos con las lneas de cdigo indicadas no se ha creado an el archivo
"archivo1.txt", tanto la clase Path como la clase File estn creando una referencia al
archivo. Ejercicio 1
Agrega un mtodo main a la clase ManejadorDeArchivos y utilizando la clase Path,
dentro del mtodo main, crea una nueva instancia del objeto apuntando a una ruta
que no exista dentro de tu mquina.
Ha sido posible la ejecucin del programa, cmo se comporta la clase Path cuando
se la trata de instanciar con una ruta a un archivo o directorio que no existe?
Como se puede notar tanto en la definicin de los objetos File y Path, el String que
hace referencia al archivo dentro del sistema de archivos, es dependiente de la
plataforma, en el caso de sistemas UNIX se pude definir de la siguiente manera
Path path2 = Paths.get("/home/ejemplos/archivo1.txt");
Una solucin para el manejo de la dependencia del separador en los directorios y
archivos es utilizar una propiedad del sistema denominada path.separator
System.getProperty("path.separator");
La clase Path permite realizar mltiples operaciones que involucran la manipulacin
de rutas dentro del sistema de archivos sin la necesidad de acceder al mismo o
modificarlo, estas son operaciones lgicas que se las realizan en memoria. Por esta
razn se dice que la clase Path trabaja a un nivel sintctico.
Debemos recordar que se puede definir Paths Absolutos y Paths relativos.
Path absoluteFilePath =
Paths.get("C:", "ejemplos", "prueba", "archivo1.txt");
Path relativeFilePath =
Paths.get("/workspace/JavaAdvanced", "src/resources","archivo1.txt");
Ejercicio 2
En los ejemplos de cdigo anteriores se muestra como obtener la referencia a una
ubicacin en el sistema de archivos utilizando varios parmetros del tipo String,
cules son las maneras de utilizar el mtodo get de la clase Path para obtener esta
referencia?
Se debe en este punto sealar que la clase Path no reemplaza al ciento por ciento a
la clase File, por lo tanto ambas pueden coexistir en una aplicacin sin ningn
inconveniente.
Como se mencion al inicio la clase Path permite realizar varias operaciones
lgicas, entre las cuales tenemos:
Manejar los diferentes niveles del Path como una estructura lineal tipo Arreglo
utilizando el mtodo getName(int posicin)
System.out.format("getName(0): %s%n", path.getName(0));
Obtener el Path absoluto a partir de un Path relativo
-
System.out.println(relativeFilePath.toAbsolutePath());
Normalizar Paths (Cuando contienen escapes de un Path a otro utilizando
puntos ..)
Path nomalizedFilePath
=Paths.get("C:/workspace/ejemplos/src/resources/dumy/../archivo1.txt")
.normalize();
Concatenacin de Paths (Join)
Path path1 = Paths.get("C:\\ejemplos"); // Result is C:\\ejemplos\\archivo1.txt System.out.format("%s%n", path1.resolve("archivo1.txt"));
Comparacin de Paths
Para esta comparacin basta con utilizar el mtodo equals de la clase Path
4. Files
La clase Files es quiz una de las ms grandes caractersticas en NIO2, ya que
soluciona muchos de los inconvenientes que presentaban cuando se trataba de
manipular archivos.
Operaciones al parecer tan simples como mover un archivo de un directorio a otro,
que con la clase File (de NIO) no se poda realizar sino copiando el archivo origen al
directorio destino y luego eliminando el archivo origen, se reducen a una invocacin
a la clase Files y su mtodo move.
4.1 Creacin de archivos
Iniciemos entonces con la creacin de un archivo utilizando File (NIO)
En este caso se crea un archivo en la raz del disco, en el caso de querer crearlo en
un directorio, el directorio debe existir o sino crearlo file.mkdir(), donde file debe
ser instanciado con la ruta del directorio
try {
File file = new File("C:\\archivo1.txt");
if (file.createNewFile()){
System.out.println("File is created!");
}else{
System.out.println("File already exists.");
}
} catch (IOException e) {
-
e.printStackTrace();
}
Revisemos ahora la creacin con un Files (NIO2)
En esta se verifica la existencia del directorio previo la creacin del archivo, ntese
que se usa el mtodo getParent de la clase Path para obtener el directorio padre del
archivo.
Path newFile = Paths.get("C:\\ejemplos\\archivo1.txt");
try {
//en primer lugar se verifica la existencia del directorio
//ejemplos caso contrario lo crea
if (Files.notExists(newFile.getParent())) {
Files.createDirectory(newFile.getParent());
}
newFile = Files.createFile(newFile);
} catch (IOException e) {
e.printStackTrace();
}
4.2 Lectura y Escritura de informacin de archivos
Para la escritura de contenido sobre un archivo se utilizan los streams o flujos
revisados con anterioridad en esta lectura. Analicemos la escritura y lectura de
archivos pequeos
NIO
public File escribirArchivo(File archivo) throws IOException {
BufferedReader entrada = new BufferedReader(new
InputStreamReader(System.in));
String linea = entrada.readLine();
FileWriter salida = new FileWriter(archivo);
salida.write(linea);
salida.write(linea);
salida.write(linea);
-
salida.close();
return archivo;
}
NIO2
Charset charset = Charset.forName("UTF-8");
List lines = new ArrayList();
lines.add(System.getProperty("line.separator"));
lines.add("Nueva linea");
lines.add("Agregada al Archivo");
lines.add("usando el mtodo write");
// After each line, this method appends the platforms line separator
(line.separator system property).
newFile = Files.write(newFile, lines, charset,
StandardOpenOption.APPEND);
Ejercicio 3
El mtodo write de la clase Files recibe un parmetro que hace referencia a las
operaciones Estndar que se pueden realizar sobre un archivo, cules son estas
operaciones? Nota. Revisar las constantes de la clase StandardOpenOption
Lectura y escritura de archivos con buffer
Charset charset = Charset.forName("UTF-8");
try (BufferedReader reader = Files.newBufferedReader(file, charset)) {
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
}
-
Escritura con buffer
Charset charset = Charset.forName("UTF-8");
String s = "Cadena de texto larga a escribir";
try (BufferedWriter writer = Files.newBufferedWriter(file, charset)) {
writer.write(s, 0, s.length());
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
}
Creando archivos temporales
String sufix = ".txt";
String prefix="JVAD";
try {
// pasando nulo en el prefijo y en sufijo toma el valor default ".tmp"
Path tempFile = Files.createTempFile(null, null);
Path tempFile1 = Files.createTempFile(prefix, sufix);
Path baseTempPath = Paths.get("c://temp");
//se puede especificar el directorio de temporales
Path tempFile2 = Files.createTempFile(baseTempPath, prefix, sufix);
} catch (IOException e) {
e.printStackTrace();
}
Moviendo un archivo
import static java.nio.file.StandardCopyOption.*;
Files.move(pathArchivoOrigen, directorioDestino, REPLACE_EXISTING);
Copiando un archivo
import static java.nio.file.StandardCopyOption.*;
-
Files.copy(pathOrigen, pathDestino, REPLACE_EXISTING);
Eliminando un archivo
try { Files.delete(path); }
catch (NoSuchFileException x) { System.err.format("%s: no such" + "
file or directory%n", path); }
catch (DirectoryNotEmptyException x) { System.err.format("%s not
empty%n", path); }
catch (IOException x) { // File permission problems are caught here.
System.err.println(x); }
5. Directorios
Para el manejo de los contenidos y creacin de directorios (carpetas) NIO2
proporciona un conjunto de mtodos de uso sencillo.
Para la copia y mover directorios se utiliza los mismos mtodos que para mover un
archivo ya que el parmetro es un Path y este puede referirse a un directorio.
5.1 Creando un directorio
try {
Path newDir = Paths.get("c://ejemplo");
if (Files.notExists(newDir)) {
newDir = Files.createDirectory(newDir);
} else {
System.out.println("Dir: " + newDir.toString() + " is already
exists.");
}
} catch (IOException e) {
e.printStackTrace();
}
5.2 Creando un directorio temporal
try {
String prefijoDirectorio = "NIO2_";
Path tempDir = Files.createTempDirectory(null);
-
System.out.println("Temp dir sin prefijo: " + tempDir.toString());
tempDir = Files.createTempDirectory(prefijoDirectorio);
System.out.println("Directorio temporal con prefijo: " +
tempDir.toString());
//para obtener la ubicacin por default del directorio temporal
System.out.println("El directorio temporal por default es: " +
System.getProperty("java.io.tmpdir"));
} catch (IOException e) {
e.printStackTrace();
}
5.3 Leyendo los contenidos de un directorio
try { Path path = Paths.get("C:\\ejemplos");
try (DirectoryStream ds = Files.newDirectoryStream(path)) {
for (Path file : ds)
{ System.out.println(file.getFileName());
}
}
} catch (IOException e) { e.printStackTrace(); }
5.4 Leyendo los contenidos de un directorio usado filtros
try {
Path path = Paths.get("C:\\ejemplos");
try (DirectoryStream ds =
Files.newDirectoryStream(path, "*.{txt}")) {
for (Path file : ds) {
System.out.println(file.getFileName());
}
}
} catch (IOException e) {
e.printStackTrace();
}
Ejercicio 5
Para el filtro de archivos se utilizar un concepto conocido como glob pattern, a que
se refiere y como se usa el glob pattern