• No se han encontrado resultados

Elabore una lista de un directorio

In document Java soluciones de programación (página 111-116)

Componentes clave

Clases Métodos

java.io.File File[ ] listFiles( )

File[ ] listFiles(FileFilter ff) String getName( ) Boolean isDirectory( ) java.io.FileFilter boolean accept(File nombre)

File define tres versiones de listFiles( ). La primera devuelve una matriz de cadenas que contiene todos los archivos (incluidos los que representan subdirectorios). Por tanto, obtiene una lista no filtrada de archivos. Se muestra aquí:

File[ ] listFiles( )

Para obtener una lista de archivos fi ltrados, puede usar una de dos formas. La usada en esta solución se muestra aquí:

File[ ] listFiles(FileFilter ff)

Obtiene una lista de sólo los archivos (y directorios) que cumplen el criterio especifi cado por ff. Dado que la matriz contiene el listado de directorios, puede obtener el nombre de cada archivo al llamar a getName( ), que está definido por File. Aquí se muestra:

String getName( )

Se devuelve la representación de cadena del archivo (o directorio).

Para restringir la lista de archivos sólo a los que cumplen con ciertos criterios, implemente un FileFilter, que es una interfaz que sólo especifica un método accept( ). Aquí se muestra:

boolean accept(File nombre)

Este método debe devolver verdadero para archivos que quiera que sean parte del listado de directorios y falso para los que serán excluidos. Dependiendo de la manera en que implemente accept( ), puede usarse para incluir todos los archivos cuyos nombres llenan un patrón general. Por ejemplo, he aquí una implementación simple que acepta todos los archivos de origen de Java: // Un filtro de archivo simple para archivos de origen de Java.

class ArchivosJava implements FileFilter { public boolean accept(File f) {

if(f.getName( ).endsWith(".java")) return true; return false;

} }

Para un fi ltrado más complejo, puede usar expresiones regulares. Con este método, puede crear fácilmente fi ltros que manejen comodines, busquen coincidencias alternas, ignoren diferencias entre mayúsculas y minúsculas, etc. (Una revisión general de las expresiones regulares se encuentra en el capítulo 2).

Ejemplo

En el siguiente ejemplo se ilustran las formas fi ltradas y no fi ltradas de listFiles( ). Para usar el programa, especifi que en la línea de comandos el nombre del directorio del que habrá de elaborarse una lista. El programa despliega primero todos los archivos del directorio especifi cado. Luego, usa un fi ltro para desplegar sólo los archivos fuente de Java.

// Despliega una lista de todos los archivos y subdirectorios // en el directorio especificado en la línea de comandos. // Por ejemplo, para desplegar la lista del contenido de // un directorio llamado \MisProgramas, use

//

// java ListaArchivos \MisProgramas //

// Un filtro de archivo simple para archivos fuente de Java. class ArchivosJava implements FileFilter {

public boolean accept(File f) {

if(f.getName( ).endsWith(".java")) return true; return false;

} }

class ListaArchivos {

public static void main(String args[ ]) {

// Primero se asegura de que se ha especificado un archivo. if(args.length != 1) {

System.out.println("Uso: ListaArchivos nombredir"); return;

}

File dir = new File(args[0]); // Confirma la existencia. if(!dir.exists( )) {

System.out.println(args[0] + " no encontrado."); return;

}

// Confirma que es un directorio. if(!dir.isDirectory( )) {

System.out.println(args[0] + " no es un directorio."); return;

}

File[ ] listaArchivos;

// Obtiene una lista de todos los archivos. listaArchivos = dir.listFiles( );

// Despliega los archivos.

System.out.println("Todos los archivos:"); for(File f : listaArchivos)

if(!f.isDirectory( )) System.out.println(f.getName( )); // Obtiene una lista de archivos fuente de Java únicamente. //

// Empieza por crear un filtro para los archivos .java. ArchivosJava aj = new ArchivosJava( );

// Ahora, pasa el archivo a list( ). listaArchivos = dir.listFiles(aj); // Despliega los archivos filtrados.

for(File f : listaArchivos)

if(!f.isDirectory( )) System.out.println(f.getName( ));

} }

Aquí se muestra una salida de ejemplo: Todos los archivos:

VolcarHex.java EscribirBytes.java CopiarArchivoBufer.java MostrarArchivo.java CopiarInvertir.java EscribirCars.java VolcarHex.class EscribirBytes.class CopiarArchivoBufer.class EscribirCars.class CopiarInvertir.class MostrarArchivo.class Archivos fuente de Java: VolcarHex.java EscribirBytes.java CopiarArchivoBufer.java MostrarArchivo.java CopiarInvertir.java EscribirCars.java

Ejemplo adicional

Las capacidades de las expresiones regulares le permiten crear fi ltros de archivo muy poderosos que usan complejos fi ltros con comodines. Las expresiones regulares también le permiten implementar fi ltros que aceptan una o más opciones. Por ejemplo, puede crear un fi ltro de archivo que acepta archivos que terminan en ".class" o ".java". He aquí otro ejemplo. Con el uso de expresiones regulares, puede crear un fi ltro de archivo que acepte archivos que contengan cualquiera de estas dos subcadenas: "bytes" o "cars". Este fi ltro aceptaría estos nombres de archivo:

EscribirBytes.java EscribirCars.java

Mediante el uso de expresiones regulares, las capacidades de un fi ltro de archivo son casi ilimitadas.

Una de las maneras más fáciles para usar una expresión regular en un filtro de archivo consiste en usar el método matches( ) de String. Recordará del capítulo 2 que tiene esta forma general:

boolean matches(String expReg)

Devuelve verdadero si la expresión regular encuentra una coincidencia en la cadena que invoca; de lo contrario, es falso.

He aquí un filtro de archivo que usa una expresión regular para buscar todos los archivos cuyo nombre contiene la secuencia "cars" o "bytes". Observe que ignora las mayúsculas y minúsculas de las letras

// Un filtro de archivo que acepta nombres que incluyen // "bytes" o "cars".

class MiFf implements FileFilter { public boolean accept(File f) {

if(f.getName( ).matches(".*(?i)(bytes|cars).*")) return true;

return false; }

}

Si se aplica este fi ltro a la misma dirección usada en el ejemplo anterior, se aceptan los siguientes archivos:

EscribirBytes.java EscribirCars.java EscribirBytes.class EscribirCars.class

Puede probar este filtro al sustituirlo en el programa de ejemplo anterior. Tal vez quiera experimentar con él un poco, probando diferentes patrones. Encontrará que las expresiones regulares ofrecen una tremenda cantidad de capacidad y control sobre el proceso de filtrado.

Opciones

Como se acaba de describir, listFiles( ) devuelve la lista de archivos como una matriz de objetos de File. Esta suele ser la forma que usted querrá. Sin embargo, puede obtener una lista que contiene sólo los nombres de los archivos en una matriz de objetos de String. Esto se hace al usar el método list( ), que también está defi nido por File. Hay dos versiones de list( ). La primera obtiene todos los archivos. Por tanto, obtiene una lista de archivos no fi ltrados. Se muestra aquí:

String[ ] list( )

Para obtener una lista de archivos fi ltrados, use esta segunda forma de list( ): String[ ] list(FilenameFilter fnf)

Obtiene una lista sólo de los archivos que cumplen el criterio especifi cado por fnf.

Observe que la forma filtrada de list( ) usa un FilenameFilter, en lugar de un FileFilter. FilenameFilter es una interfaz que ofrece una manera alterna de construir un filtro: sólo especifica un método, accept( ), que se muestra aquí:

boolean accept(File dir, String nombre)

En este método, el directorio se pasa a dir y el nombre de archivo a name. Debe devolver verdadero para archivos que coinciden con el nombre de archivo especifi cado por nombre. De otra manera, devuelve falso.

Puede usar FilenameFilter con listFiles( ) para obtener una lista de archivos filtrada. Aquí se muestra esta forma de listFiles( ):

Como se mencionó cerca del principio del capítulo, Java proporciona clases de fl ujo que comprimen y descomprimen automáticamente los datos. Estas clases están empaquetadas en java.util.zip. Cuatro de estas clases se usan para leer y escribir archivos GZIP y ZIP estándares. Sin embargo, también es posible usar el algoritmo de compresión directamente, sin crear uno de estos archivos estándar. Hay una muy buena razón por la que desearía hacer esto: le permite a su aplicación operar de manera directa sobre datos comprimidos. Esto podría resultar especialmente valioso cuando se usan archivos de datos muy grandes.

Por ejemplo, una base de datos que contiene un inventario de un vendedor en línea muy grande podría contener varios miles de entradas. Al almacenar esa base de datos en forma comprimida, su tamaño puede reducirse de manera importante. Debido a que los flujos de archivo comprimidos de Java le dan la capacidad de leer y escribir un archivo comprimido directamente, todas las operaciones de archivo pueden tomar lugar sobre el archivo comprimido, sin la necesidad de crear una copia descomprimida. En esta solución se muestra la manera de implementar este esquema. Como verá, el uso de datos comprimidos es muy fácil porque incluye una capa superior casi transparente para el manejo básico de archivos requerido por la aplicación.

En la base de la biblioteca de compresión se encuentran las clases Deflater e Inflater. Proporcionan el algoritmo que comprime y descomprime los datos. Como se mencionó cerca del inicio de este capítulo, la implementación predeterminada de estas clases usa la biblioteca de compresión ZLIB. Los flujos de datos comprimidos, definidos por java.util.zip, usan las implementaciones predeterminadas de estas clases. Estas implementaciones predeterminadas son adecuadas para casi todas las tareas de compresión, y por lo general no necesitará interactuar directamente con Deflater o Inflater.

En esta solución se usa DeflaterOutputStream para escribir en un archivo de datos comprimidos e InflaterInputStream para leer un archivo de datos comprimido. DeflaterOutputStream se deriva de OutputStream y FilterOutputStream e implementa las interfaces Closeable y Flushable. InflaterInputStream se deriva de InputStream y FilterInputStream e implementa la interfaz Closeable.

Paso a paso

Para comprimir datos y escribirlos en un archivo se requieren estos pasos: 1. Cree un flujo de archivo que use DeflaterOutputStream.

2. Escriba la salida en la instancia de DeflaterOutputStream. Puede usar uno de los métodos estándar de write( )para escribir los datos. Sin embargo, a menudo un DeflaterOutputStream se envuelve en un DataOutputStream, que le permite escribir convenientemente tipos de datos primitivos, como int y double. En cualquier caso, los datos se comprimirán automáticamente. 3. Cierre el flujo de salida cuando termine de escribir.

In document Java soluciones de programación (página 111-116)