Clase File
Podes consultar na web de Oracle a documentación de la biblioteca estándar de clases de java.
Constructores
- File(String ruta)
- File(String ruta, String nombre)
- File(File directorio, String nombre)
Metodos
- canRead() e canWrite() : comproba se o ficheiro se pode ler/escribir
- delete(): borra o ficheiro
- exists(): devolve boolean si existe el fichero
- getPath(): devolve a ruta do ficheiro
- mkdir(): crea un directorio coa ruta do obxecto que o recibe. Hay una versión que es mkdirs() que se usa para crear una jerarquía de directorios
- isDirectory() comproba se o ficheiro é un directorio
Pódese usar rutas absolutas como no siguinte exemplo pero es totalmente recomendable usar rutas relativas:
File prueba = new File("c:\\midirectorio\\prueba.txt");
if(!prueba.exists())
System.out.println("c:\\midirectorio\\prueba.txt NO existe");
if(!new File("c:\\midirectorio").exists())
System.out.println("c:\\midirectorio NO existe");
if(!new File("m:").exists())
System.out.println("m: NO existe");
if(new File("l:\\midirectorio\\prueba.txt").exists())
System.out.println("l:\\midirectorio\\prueba.txt existe");
Exemplo de mkdirs:
String directorio = "l:/micarpeta";
String varios = "carpeta1/carpeta2/carpeta3";
// Crear un directorio
boolean exito = (new File(directorio)).mkdir();
if (exito)
System.out.println("Directorio: " + directorio + " creado");
// Crear varios directorios
exito = (new File(directorio+"/"+varios)).mkdirs();
if (exito)
System.out.println("Directorios: " + varios + " creados");
Podes atopar na coñecida web de referencia w3schools exemplos explicativos con código de manexo de ficheiros con estes métodos.
Con todo, dende Java SE 7, existe un xeito mellor de xestionar os ficheiros: java.nio.
Entón, se existe unha forma máis axeitada de xestionar os ficheiros en Java… por que aprendemos a utilizar esta? Porque debido o enorme número de aplicacións que usan a antigua API (o que se chame legacy), Oracle non ten plan de eliminar ou desaconsellar o seu uso nas vindeiras versións de Java. E por iso, porque podes atopar un montón de código en funcionamento o que lle tes que dar mantemento (ou facer migración), e que non vai desaparecer de xeito inminente, e bo coñecer esta API.
java.nio para xestión de ficheiros e directorios
Agora que xa coñecemos esta nova posibilidade de traballar con ficheiros, que permite contar con toda a funcionalidade que se acadaba antes, indagaremos sobre cales son as melloras que trae e como traballar coa novaAPI.
Melloras de java.nio
Cales son esas melloras na xestión? Por unha banda, permite facer unha mellor xestión de erros. Poñamos este código de exemplo
File file = new File("probas/titorial.txt");
boolean result = file.delete()
Compila e pode funcionar mais no caso de fallar… como saberemos se é porque o ficheiro non existe, ou é porque non temos permisos para borrar?
Reescribindo o código coa nova NIO2 API:
Path path = Paths.get("probas/titorial.txt");
Files.delete(path);
Agora será preciso xestionar unha IOException, que dará os detalles de que foi o que aconteceu (por exemplo, non ter permisos de borrado).
A nova versión tamén mellora o soporte ós metadatos e trae melloras de rendemento evitando problemas de insuficiencia de memoria.
Diferencias con file e como facer uso de java.nio
A primeira diferencia que salta rápido a vista dun programador é o cambio no nome do paquete e da clase (observables en letra grosa os cambios). Antes construíamos un obxecto file vía o construtor:
java.io.File file = new java.io.File("probas/titorial.txt");
Agora obteremos un Path usando un método static (get):
java.nio.file.Path path = java.nio.file.Paths.get("probas/titorial.txt");
Para crear ficheiros usaremos os métodos createNewFile() e Files.createFile():
boolean result = file.createNewFile();
Path newPath = Files.createFile(path);
//Para crear un directorio, mkdir() ou Files.createDirectory():
boolean result = file.mkdir();
File newPath = Files.createDirectory(path);
Hai variantes para incluir subdirectorios que non existan con mkdirs() e Files.createDirectories():
boolean result = file.mkdirs();
File newPath = Files.createDirectories(path);
Para renomear ou mover un ficheiro, precisamos crear outra instancia do obxecto e usar renameTo() ou Files.move():
boolean result = file.renameTo(new File("baeldung/tutorial2.txt"));
Path newPath = Files.move(path, Paths.get("baeldung/tutorial2.txt"));
Finalmente para borrar, usaremos delete() ou Files.delete():
boolean result = file.delete();
Files.delete(Paths.get(path));
Lembra que os métodos legacy devolven un flag cun result set a falso en caso de erro; e os métodos NIO2 devolve unha instancia de Path instance (agás a operación de borrado que lanza unha IOException en caso de erro).
Exercicio 1
Cal sería o código para saber se o indicado no path é u ficheiro? E se é posible escribir no mesmo? Amosa o código de xeito tradicional e coa nova API NIO.
Exercicio 2
En args[0] indicas un directorio e o programa imprime seu contido (no recursivo). Exemplo:
Faino con File e NIO
Exercicio 3
Como no anterior pero agora o programa imprime o contido de forma recursiva. Hai varias maneiras unha é directamente coa clase File e utilizando o método utilidad fileList().
Creando un ficheiro
Podemos crear un ficheiro baleiro cos atributos que desexemos co método: createFile(Path, FileAttribute); Se non se especifican os atributos, será creado con atributos por defecto. E de xa existir o ficheiro indicado na ruta, lanzarase unha excepción. O seguinte código crea un ficheiro con atributos por defecto:
Path file = ...;
try {
// Create the empty file with default permissions, etc.
Files.createFile(file);
} catch (FileAlreadyExistsException x) {
System.err.format("O ficheiro chamado %s" + " xa existe%n", file);
} catch (IOException x) {
// Outro tipo de fallo, coma os relacionados con permisos.
System.err.format("createFile da erro: %s%n", x);
}
Creando un directorio
Pódese facer usando o método:
createDirectory(Path, FileAttribute);
Se non se especifica ningún atributo, terá os que correspondan por defecto.
Un exemplo:
Path dir = ...;
Files.createDirectory(path);
Mostrando o contido dun directorio
Pódese facer usando o método: newDirectoryStream(Path);
Este método devolve un obxecto que implementa a interfaz DirectoryStream, que a súa vez implementa Iterable.
Recorda que o devolto DirectoryStream é un fluxo, e que se non o chamas desde un try-with-resources debes pechar o fluxo no bloque finally.
A continuación un exemplo que amosa os contidos dun directorio:
Path dir = ...;
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path file: stream) {
System.out.println(file.getFileName());
}
} catch (IOException | DirectoryIteratorException x) {
// IOException nunca será lazanda pola iteracion neste exemplo
// so pode ser lanzado por newDirectoryStream.
System.err.println(x);
}
Borrando un ficheiro, enlace simbólico ou directorio
Debes ter en conta que para borrar un directorio este non debe ter contido, ou a operación de borrado fallará. Cando o que se borra é un enlace simbólico, o destino do enlace non será borrado.
A clase File facilita dous métodos para o borrado.
O método delete(Path) → borra o ficheiro ou lanza unha excepción se a operación falla (por exemplo, non existe a excepción ou non se gozan dos permisos requiridos.
Por exemplo:
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);
}
O método deleteIfExists(Path) → a diferencia do anterior, non lanzará excepción se o ficheiro non existe (o cal pode ser útil cando se traballa con varios fíos).
Copiando un ficheiro ou directorio
Para copiar un ficheiro ou directorio existe o método:
copy(Path, Path, CopyOption…);
A copia falla se o destino existe agás a opción REPLACE_EXISTING se atope indicada.
Os directorios poden ser copiados, pero debese ter en contacta que os ficheiros contidos na ruta orixe non o serán: o novo directorio sempre será creado baleiro.
O seguinte código exemplifica o funcionamento do método copy (recorda que será preciso importar o paquete con import static java.nio.file.StandardCopyOption.*):
Files.copy(orixe, destino, StandardCopyOption.REPLACE_EXISTING);
Existen outros métodos da clase Files que permiten facer a copia entre un ficheiro e un fluxo:
- copy(InputStream, Path, CopyOptions…) → todos os bytes dun dun fluxo de entrada a un ficheiro
- copy(Path, OutputStream) → todos os bytes dun ficheiro a un fluxo de saída
Movendo un ficheiro ou directorio
É posible mover un ficheiro e directorio usando move(Path, Path, CopyOption…)
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
Neste exemplo empregouse a opción REPLACE_EXISTING que sobreescribe de xa existir na ruta de destino o ficheiro ou directorio
Exercicio 4
Investiga la interfaz Path para obtener estos datos de un ruta:
- Ruta do directorio pai
- Número de elementos que compoñe a ruta
- Obter o nome do arquivo (se o ten)
Partindo doutra ruta para o destino, copia un fichero de una carpeta a outra. Finalmente borra o path orixe.
Extra: relación y conversión entre Path y File
Entre a Interface Path e a classe File existen mecanismos para obter unha representación dun tipo o outro. No JDK7 non é necesario realizar operacións de conversión complexas soamemte é necesario recurrir ó método .toFile de cada un de eles:
- path.toFile(): Retorna un obxecto File representando sua ruta.
- file.toPath(): Retorna un obxecto de tipo Path construido dende unha ruta abstracta. O obxecto Path resultante encontrase asociado co sistema de arquivos por defecto.