Manejo de Archivos en Java

Embed Size (px)

DESCRIPTION

manejo de archivos java

Citation preview

  • 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