Xestión de erros e excepcións enfocada o uso de ficheiros
Xestión de erros e excepcións
Non debe ser o tratamento de excepcións o tema central das explicacións para a xestión de ficheiros. Con todo, xa que o seu tratamento será preciso, faremos unha breve exposición simplificada das diversas posilibadaes para capturas os erros.
try-catch
O código que manipule ficheiros poderá ter a seguinte estrutura
try{
//Código que abre e trata o ficheiro
} catch (IOException ex){
//Código que trata o erro
}
https://docs.oracle.com/javase/tutorial/essential/exceptions/try.html https://docs.oracle.com/javase/tutorial/essential/exceptions/catch.html
throws
Se no canto de tratar o erro nos queremos indicar que o noso método pode lanzar excepcións:
public int methodThatCanThrow(params) throws IOException{
//Código que trata ficheiros pero non atrapa IOException
}
finally
O bloque finally contén código importante que será executado indistintamente de que salte unha excepción ou non. No caso de ficheiros, será habitual incluir neste bloque o peche do stream, para asegurar que todas os ficheiros abertos son pechados apropiadamente; e así, os datos dos ficheiros non se poderán corromper.
import java.io.*;
public class SimpleExceptionHandling {
public static void main(String[] args) { FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream("C:\\UnFicheiroTemporal");
} catch (FileNotFoundException e) { System.out.println("Aconteceu a excepción :: " + e.getMessage()); System.out.println("Necesitamos pechar FileStream!"); } finally { System.out.println("Afortunadamente pecharase neste bloque"); try { if (fileInputStream != null) { fileInputStream.close(); } } catch (IOException e) { } } }
}
Saída:
Aconteceu a expeción :: C:\UnFicheiroTemporal (The system cannot find the file specified) Necesitamos pechar FileStream! Afortunadamente pecharase neste bloque
E importante remarcar que o finally tamén se executaría no caso de non terse producida a excepción.
https://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html https://www.geeksforgeeks.org/why-you-need-to-close-the-java-streams-in-finally-block/
try-with-resources
Mecanismo que automáticamente pecha recursos (pode ser máis de un) cando se acabou o seu traballo con eles.
Por exemplo:
private static void printFile() throws IOException {
try(FileInputStream input = new FileInputStream("ficheiro.txt")) {
int data = input.read();
while(data != -1){
System.out.print((char) data);
data = input.read();
}
}
}
Neste exemplo ábrese un FileInputStream dentro dun bloque a try-with-resources block, lee datos do FileInputStream, e pechao automaticamente cando a execución sae do bloque. Isto último e posible porque FileInputStream implementa a interface java.lang.AutoCloseable.
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html http://tutorials.jenkov.com/java-exception-handling/try-with-resources.html
Exercicio para adaptar código para a xestión correcta de recursos e excepcións.
Un apartado →https://jesusfernandeztoledo.com/ejercicios-resueltos-ficheros-en-java/ Otro apartado de adaptar un código que quieras a try -with-resources Y último: pag 27 sin excepciones y que se pongan. Sol→ https://www.unirioja.es/cu/jearansa/0910/archivos/EIPR_Tema05.pdf
2. A clase File Utilizaremos a versión de Java JDK 17, unha versión LTS (long term support, con soporte a largo prazo).
Podes consultar a documentación dea biblioteca estándar de clases en https://docs.oracle.com/en/java/javase/17/ .
En concreto as clases que permiten traballar con ficheiros están no paquete java.io, onde na ***documentación premendo sole el atoparás a lista de interfaces e clases que contén o paquete.
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/File.html
O máis relevante pódes atopalo a continuación: Constructores File(String ruta) File(String ruta, String nombre) File(File directorio, String nombre) Métodos canRead() e canWrite() : comproba se o ficheiro se pode ler/escribir delete(): borra o ficheiro getPath(): devuelve a ruta do ficheiro mkdir(): crea un directorio coa ruta do obxecto que o recibe isDirectory() comproba se o ficheiro é un directorio
Podes atopar na coñecida web de referencia w3schools exemplos explicativos con código de manexo de ficheiros con estes métodos: https://www.w3schools.com/java/java_files.asp
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 qué 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
Exercicio: adaptar copia de ficheiros para uso de excepcións
Exercicio de ampliación: serialización de obxectos 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 qué melloras trae e como traballar coa nova API.. 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… cómo saberemos se é porque o ficheiro non existe, ou é porque non temos permisos para borrar?
Rescribindo 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):
java.io.File file = new java.io.File("probas/titorial.txt");
java.nio.file.Path path = java.nio.file.Paths.get("probas/titorial.txt");
Antes construíamos un obxecto file via o construtor; agora obteremos un Path usando un método static (get).
Podemos obter o mesmo resultado encadeando o método resolve: Path outroXeitoPath = Paths.get("probas").resolve("titorial.txt");
Finalmente, é posibel convertir obxectos entre APIs:
Path pathFromFile = file.toPath(); File fileFromPath = path.toFile();
Both APIs deliver methods to manage files and directories. We'll demonstrate this using the previously created instance objects.
Para crear files 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 para indagar sobre metadatos Sabemos cómo consultar se un file existe con java.io e java.nio API // java.io API boolean fileExists = file.exists();
// java.nio API boolean pathExists = Files.exists(path);
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 para as dúas apis:
Solución // java.io API boolean fileIsFile = file.isFile(); boolean fileWritable = file.canWrite();
// java.nio API boolean pathIsFile = Files.isRegularFile(path); boolean pathWritable = Files.isWritable(path); https://www.baeldung.com/java-path-vs-file
Exercicio para indagar sobre rutas (absoluta e canónica) Consulta a ruta canónica é absoluta dun ficheiro (o que ti escollas). Amosa o código para as dúas APIs.:
Solución // java.io API
String absolutePathStr = file.getAbsolutePath(); String canonicalPathStr = file.getCanonicalPath();
// java.nio API
Path absolutePath = path.toAbsolutePath(); Path canonicalPath = path.toRealPath().normalize();
Exercicio para indagar sobre rutas (absoluta e canónica) Consulta a ruta canónica é absoluta dun ficheiro (o que ti escollas). Amosa o código para as dúas APIs.:
Solución // java.io API
String absolutePathStr = file.getAbsolutePath(); String canonicalPathStr = file.getCanonicalPath();
// java.nio API
Path absolutePath = path.toAbsolutePath(); Path canonicalPath = path.toRealPath().normalize();
Explicación. While the Path object is immutable, it returns a new instance. Moreover, the NIO2 API has the toRealPath() and normalize() methods that we can use to remove redundancies.
Exercicio para amosar os contidos dun directorio Amosa o contido do directorio da túa elección
Solución
// java.io API String[] list = file.list(); File[] files = file.listFiles();
// java.nio API DirectoryStream<Path> paths = Files.newDirectoryStream(path);
A API NIO2 devolve o seu propio obxecto DirectoryStream object, que implementa a interface iterable.
Exercicio 10_1 e pedir recursividade
BBB
B