Gestió de fitxers

Entre les funcions d’un sistema operatiu hi ha la d’oferir mecanismes genèrics per gestionar sistemes de fitxers. Normalment, dins un sistema operatiu modern (o ja no tant modern), s’espera disposar d’algun tipus d’interfície o explorador per poder gestionar fitxers, ja sigui gràficament o usant una línia d’ordres de text. Si bé la manera com les dades es desen realment en els dispositius físics d’emmagatzematge de dades pot ser molt diferent segons cada tipus (magnètic, òptic, etc.), la manera de gestionar el sistema de fitxers sol ser molt similar en la immensa majoria dels casos: una estructura jeràrquica amb carpetes i fitxers.

Ara bé, en realitat, la capacitat d’operar amb el sistema de fitxers no és exclusiva de la interfície oferta pel sistema operatiu. Molts llenguatges de programació proporcionen biblioteques que permeten accedir directament als mecanismes interns que ofereix el sistema, de manera que és possible crear codi font des del qual, amb les instruccions adients, es poden realitzar operacions típiques d’un explorador de fitxers. De fet, les interfícies ofertes, com un explorador de fitxers, són un programa com qualsevol altre, el qual, usant precisament aquestes llibreries, permet que l’usuari gestioni fitxers fàcilment. Però no és estrany trobar altres aplicacions amb la seva pròpia interfície per gestionar fitxers, encara que només sigui per poder seleccionar quin cal carregar o desar en un moment donat: editors de text, compressors, reproductors de música, etc.

Java no és cap excepció oferint aquest tipus de biblioteca, en forma del conjunt de classes incloses dins del package java.io. Mitjançant la invocació dels mètodes adients definits d’aquestes classes, és possible dur a terme pràcticament qualsevol tasca sobre el sistema de fitxers.

La classe File

La peça més bàsica per poder operar amb fitxers, independentment del seu tipus, en un programa fet en Java és el tipus compost File. Aquesta classe pertany al package java.io. Per tant, l’haureu d’importar abans de poder usar-la. Aquesta us permet manipular qualsevol aspecte vinculat al sistema de fitxers. Ara bé, cal anar amb compte, ja que el seu nom (“fitxer”, en anglès) és una mica enganyós, ja que no es refereix exactament a un fitxer.

La classe File indica, més concretament, una ruta dins el sistema de fitxers.

Concretament, serveix per fer operacions tant sobre rutes al sistema de fitxers que ja existeixin com no existents. A més a més, aquesta classe es pot usar tant per manipular fitxers de dades com carpetes.

Inicialització

Com qualsevol altra classe, abans de poder treballar amb File, a part d’importar-la correctament, cal inicialitzar-la, de manera que sigui possible invocar els seus mètodes. En aquest cas, per fer-ho cal incloure com a paràmetre una cadena de text corresponent a la ruta sobre la qual es volen dur a terme les operacions.

  1. File f = new File (String ruta)

Una ruta és la forma general d’un nom de fitxer o carpeta, de manera que identifica únicament la seva localització en el sistema de fitxers.

Cadascun dels elements de la ruta poden existir realment o no, però això no impedeix de cap manera poder inicialitzar File. En realitat, el seu comportament és com una declaració d’intencions sobre quina ruta del sistema de fitxers es vol interactuar. No és fins que es criden els diferents mètodes definits a File, o fins que s’hi escriuen o s’hi llegeixen dades, que realment s’accedeix al sistema de fitxers i es processa la informació.

Cal tenir sempre present si el sistema operatiu distingeix entre majúscules i minúscules o no.

Un aspecte important que cal tenir present en inicialitzar File és tenir sempre present que el format de la cadena de text que conforma la ruta pot ser diferent segons el sistema operatiu sobre el qual s’executa l’aplicació. Per exemple, el sistema operatiu Windows inicia les rutes per un nom d’unitat (C:, D:, etc.), mentre que els sistemes operatius basats en Unix comencen directament amb una barra (”/”). A més a més, els diferents sistemes operatius usen diferents separadors dins les rutes. Per exemple, els sistemes Unix usen la barra (”/”) mentre que el Windows la contrabarra (“\”).

  • Ruta Unix: /usr/bin
  • Ruta Windows: C:\Windows\System32

Per generar aplicacions totalment portables en diferents sistemes, la classe File ofereix la possibilitat d’accedir a una constant declarada dins d’aquesta classe per especificar separadors de ruta dins una cadena de text de manera genèrica, anomenada File.separator. Quan s’usa, el seu valor és el que correspon segons el sistema operatiu on s’executa el programa. L’accés a aquesta constant es fa de manera molt semblant a com s’invoca un mètode estàtic.

  1. File f = new File(File.separator + "usr" + File.separator + "bin");

De totes maneres, Java adopta per defecte el sistema Unix com a separador per defecte (usant la barra, /), independentment del sistema operatiu. Per tant, en un sistema Windows és possible separar una ruta amb aquest caràcter i Java ho sabrà interpretar correctament. A partir d’ara, tots exemples es basaran en un sistema Windows (rutes iniciades amb un nom d’unitat,, C:, D:, etc.), però s’usarà la barra per referir-se a qualsevol ruta.

Per escriure una contrabarra a una cadena de text cal escriure ‘\’.

De fet, en fer un programa en Java en un sistema Windows cal ser especialment acurat amb aquest fet, ja que la contrabarra no és un caràcter permès dins una cadena de text, i serveix per declarar valors especials d’escapament (\n salt de línia, \t tabulador, etc.).

Un altre aspecte molt important en inicialitzar File és que es tracta d’una classe que defineix un tipus compost (com String), i no un simple repositori de mètodes (com Scanner o Random). En conseqüència, cada cop que s’inicialitza, a l’identificador emprat s’hi assigna un valor associat a aquella ruta. A partir de llavors, l’identificador actua com una variable dins el programa. Per operar amb diferents rutes alhora caldrà inicialitzar i manipular diferents variables, igual que es faria amb diferents cadenes de text.

Per exemple, en el codi següent es declaren tres variables diferents, cadascuna de les quals emmagatzema un valor de tipus File diferent. Per treballar amb cada ruta, ja sigui carpeta o fitxer, caldrà usar la variable corresponent.

  1. ...
  2. File carpetaFotos = new File("C:/Personal/LesMevesFotos");
  3. File unaFoto = new File("C:/Personal/LesMevesFotos/Foto1.png");
  4. File unaAltraFoto = new File("C:/Personal/LesMevesFotos/Foto2.png");
  5. ...

Rutes relatives i absolutes

En els exemples emprats fins al moment per inicialitzar variables del tipus File s’han usat rutes absolutes, ja que és la manera de deixar més clar a quin element dins del sistema de fitxers, ja sigui fitxer o carpeta, s’està fent referència.

Una ruta absoluta és aquella que es refereix a un element destinació a partir de la carpeta arrel d’un sistema de fitxers. En aquesta s’enumeren, una per una, totes les carpetes que hi ha entre la carpeta arrel fins a la carpeta que conté l’element destinació.

Les rutes absolutes es distingeixen fàcilment, ja que el text que les representa comença d’una manera molt característica depenent del sistema operatiu de l’ordinador. En el cas dels sistemes operatius Windows al seu inici sempre es posa el nom de la unitat (“C:”, “D:”, etc.), mentre que en el cas dels sistemes operatius Unix, aquestes comencen sempre per una barra (”/”).

Per exemple, les cadenes de text següents representen rutes absolutes dins un sistema de fitxers de Windows:

  • C:\Fotos\Viatges (ruta a una carpeta)
  • M:\Documents\Unitat6\Apartat1 (ruta a una carpeta)
  • N:\Documents\Unitat6\Apartat1\Activitats.txt (ruta a un fitxer)

En canvi, en el cas d’una jerarquia de fitxers sota un sistema operatiu Unix, un conjunt de rutes podrien estar representades de la manera següent:

  • /Fotos/Viatges (ruta a una carpeta)
  • /Documents/Unitat6/Apartat1 (ruta a una carpeta)
  • /Documents/Unitat6/Apartat1/Activitats.txt (ruta a un fitxer)

En inicialitzar variables de tipus File usant una ruta absoluta, sempre cal usar la representació correcta segons el sistema en què s’executa el programa.

Si bé l’ús de rutes absolutes resulta útil per indicar amb tota claredat quin element dins el sistema de fitxers s’està manipulant, hi ha casos que el seu ús comporta certes complicacions. Suposeu que heu fet un programa en el qual es duen a terme operacions sobre el sistema de fitxers. Un cop veieu que funciona, deixeu el projecte Java a un amic, que el copia al seu ordinador dins d’una carpeta qualsevol i l’obre amb el seu entorn de treball. Perquè el programa li funcioni perfectament, abans caldrà que al seu ordinador hi hagi exactament les mateixes carpetes que heu usat al vostre ordinador, tal com estan escrites en el codi font del vostre programa. En cas contrari, no funcionarà, ja que les carpetes i fitxers esperats no existiran, i per tant, no es trobaran. Usar rutes absolutes fa que un programa sempre hagi de treballar amb una estructura del sistema de fitxers exactament igual sigui on sigui on s’executi, cosa no gaire còmoda.

Per resoldre aquest problema, a l’hora d’inicialitzar una variable de tipus File, també es pot fer referint-se a una ruta relativa.

Una ruta relativa es aquella que es considera que parteix des de la carpeta, o directori, de treball de l’aplicació. Aquesta carpeta pot ser diferent cada cop que s’executa el programa i depèn de la manera com s’ha dut a terme aquesta execució.

En els sistemes Windows, dins de les propietats d’una drecera, hi ha una opció per especificar el “Directori de treball” de la seva aplicació associada.

Quan un programa s’executa, ja sigui en Java o en qualsevol altre llenguatge de programació, per defecte se li assigna una carpeta de treball. Aquesta carpeta sol ser, per defecte, la carpeta des d’on es llença el programa, si bé hi ha sistemes operatius que permeten especificar-la explícitament mitjançant alguna opció sobre les seves dreceres o fitxers executables. En el cas d’un programa en Java executat a través d’un IDE, la carpeta de treball sol ser la mateixa carpeta on s’ha triat desar els fitxers del projecte.

El format d’una ruta relativa és semblant a una ruta absoluta, però mai s’indica l’arrel del sistema de fitxers. Directament es comença pel primer element escollit dins la ruta. Per exemple:

  • Viatges
  • Unitat6\Apartat1
  • Unitat6\Apartat1\Activitats.txt

La propietat especial d’una ruta relativa és que, implícitament, es considera que aquesta sempre inclou el directori de treball de l’aplicació com a part inicial del text, tot i no haver-se escrit. Ara bé, el tret distintiu és que, precisament, aquest directori de treball pot variar. Per exemple, donada la inicialització següent, l’element al qual es refereix la ruta varia segons com indica la taula:

  1. File f = new File ("Unitat6/Apartat1/Activitats.txt");
Taula Rangs i paraules clau dels tipus primitius numèrics a Java
Directori de treball Ruta real
C:\Projectes\Java C:\Projectes\Java\Unitat6\Apartat1\Activitats.txt
D:\Unitats X:\Unitats\Unitat6\Apartat1\Activitats.txt
/Programes /Programes/Unitat6/Apartat1/Activitats.txt

Aquest mecanisme permet minimitzar el nombre de carpetes que cal garantir que hi ha quan executem programes en diferents equips, ja que només cal controlar la vinculada a la ruta relativa. La part vinculada al directori de treball varia automàticament per cada versió copiada en cada màquina. En el cas més senzill d’entendre, suposeu la inicialització següent:

  1. File f = new File ("Activitats.txt");

Donada aquesta ruta, n’hi ha prou a garantir que el fitxer “Activitats.txt” està sempre al mateix directori de treball de l’aplicació, sigui quin sigui aquest (en un ordinador pot ser “C:\Programes”, en un altre ”/Java”, etc.). En qualsevol de tots aquests casos, la ruta sempre serà correcta. De fet, encara més. Noteu com les rutes relatives a Java permeten crear codi independent del sistema operatiu, ja que no cal especificar un format d’arrel lligada a un sistema de fitxers concret (“C:”, “D:”, ”/”, etc.).

Java disposa de dues instruccions per consultar quina és la carpeta de treball d’un programa i canviar-la per un altre, si així es vol fer. De totes maneres, normalment es deixa la carpeta que assigna per defecte el sistema operatiu en executar el programa.

  1. //Assigna en forma de cadena de text la ruta de la carpeta de treball actual.
  2. String dirTreball = System.getProperty("user.dir");
  1. //Indica quina és la ruta de la nova carpeta de treball a partir d'una cadena de text.
  2. String nouDirTreball = "...";
  3. System.setProperty("user.dir", nouDirTreball);

De totes maneres, a mesura que aneu veient com realitzar operacions amb fitxers a partir de rutes, es veurà més clar el funcionament de rutes relatives i absolutes.

Operacions típiques de la classe File

Al contrari que les cadenes de text, el tipus compost File no permet usar absolutament cap mena d’operador, ni tant sols el '+'. Qualsevol operació que es vulgui dur a terme amb una ruta s’haurà de fer mitjançant la invocació de mètodes sobre la variable corresponent. En aquest sentit, File ofereix diversos mètodes per poder manipular el sistema de fitxers o obtenir informació a partir de la seva ruta. Alguns dels més significatius per entendre’n les funcionalitats es mostren tot seguit, ordenats per tipus d’operació.

Aquest cop, per descriure cada mètode s’emprarà la seva definició tal com apareix a la documentació del Java, especificant el tipus del valor de retorn i dels seus paràmetres.

Obtenció de la ruta

Un cop s’ha inicialitzat una variable de tipus File, pot ser necessari recuperar la informació emprada durant la seva inicialització i conèixer en format text a quina ruta s’està referint, o com a mínim part d’ella.

  • String getParent() avalua la ruta de la carpeta pare de l’element referit per aquesta ruta. Bàsicament, la cadena de text resultant és idèntica a la ruta original usada en inicialitzar la variable de tipus File, eliminant el darrer element. Si la ruta tractada es refereix a la carpeta arrel d’un sistema de fitxers (“C:\”, ”/”, etc.), aquest mètode avalua null. En el cas de tractar-se d’una ruta relativa, aquest mètode no inclou la part de la carpeta de treball.
  • String getName() avalua El nom de L’element que representa aquesta ruta, ja sigui una carpeta o un fitxer. Es tracta del cas invers del mètode getParent(), ja que el text resultant és només el darrer element, descartant la resta del text de la ruta prèvia.
  • String getAbsolutePath() avalua el text relatiu a la ruta absoluta. Si la variable File es va inicialitzar usant una ruta relativa, el resultat inclou també la part associada a la carpeta de treball.

La figura mostra un resum del text que avalua cada mètode, donada una ruta concreta.

Figura Avaluació dels mètodes d’obtenció de ruta a File

El programa següent mostra un exemple de com funcionen aquests tres mètodes. Noteu com a les rutes relatives se’ls afegeix la carpeta de treball, que serà la carpeta on teniu el vostre projecte amb el codi font del programa.

  1. package unitat6.apartat1.exemples;
  2. //Cal importar la classe File
  3. import java.io.File;
  4. public class FileObtenirRuta {
  5. public static void main(String[] args) {
  6. FileObtenirRuta programa = new FileObtenirRuta();
  7. programa.inici();
  8. }
  9. public void inici() {
  10. //S'inicialitzen dues rutes absolutes diferents
  11. File carpetaAbs= new File ("c:/Temp");
  12. File fitxerAbs = new File ("c:/Temp/Document.txt");
  13. //I unes rutes relatives
  14. File carpetaRel = new File ("Temp");
  15. File fitxerRel = new File ("Temp/Document.txt");
  16. //Mostrem les dades de cadascuna
  17. mostrarRutes(carpetaAbs);
  18. mostrarRutes(fitxerAbs );
  19. mostrarRutes(carpetaRel );
  20. mostrarRutes(fitxerRel );
  21. }
  22. public void mostrarRutes(File f) {
  23. System.out.println("La ruta és " + f.getAbsolutePath());
  24. System.out.println("El seu pare és " + f.getParent());
  25. System.out.println("El seu nom és " + f.getName() + "\n");
  26. }
  27. }

Comprovacions d'estat

Donada la ruta emprada per inicialitzar una variable de tipus File, aquesta pot ser que realment existeixi dins el sistema de fitxers o no, ja sigui en forma de fitxer o carpeta. La classe File ofereix un conjunt de mètodes que permeten fer comprovacions sobre el seu estat i saber si és així.

boolean exists() comprova si la ruta existeix dins del sistema de fitxers o no. Avaluarà true o false, per a cada cas, respectivament. Es considera que la ruta no existeix si qualsevol dels elements individuals que la conformen no existeix.

Normalment, donat el text d’una ruta, els fitxers es distingeixen de les carpetes pel seu format, en tenir extensió (l’últim element de la ruta sol ser de la forma nom.extensió, com Foto1.jpg o Document.txt). Tot i així, cal tenir en compte que l’extensió no és un element obligatori en el nom d’un fitxer, només s’usa com a mecanisme perquè tant l’usuari com alguns programes puguin discriminar més fàcilment tipus de fitxers. Per tant, només amb el text d’una ruta no es pot estar 100% segur de si aquesta es refereix a un fitxer o a una carpeta. Per poder estar realment segurs, es poden usar els mètodes següents:

  • boolean isFile() permet comprovar si la ruta es refereix a un fitxer (avaluant true) o no (avaluant false). Aquesta comprovació no es duu a terme únicament sobre el text de la ruta, sinó que es mira al sistema de fitxers si la ruta existeix, i llavors es mira si l’element amb aquest nom es tracta d’un fitxer o carpeta. Si no existeix, sempre s’avalua a false.
  • boolean isDirectory() funciona igual que l’anterior, però comprovant si es tracta d’una carpeta.

Per exemple, el programa següent fa un seguit de comprovacions sobre un conjunt de rutes. Per poder-lo provar de manera efectiva, però, caldria preparar el sistema de fitxers del vostre ordinador. Per exemple, podeu crear una carpeta anomenada “Temp” a l’arrel de la unitat “C:”. Dins d’aquesta, creeu-ne una altra anomenada “Fotos”. A la mateixa carpeta “Temp”, creeu un nou fitxer (que pot estar buit) anomenat “Document.txt”. Després, esborreu la carpeta o el document i torneu a executar el programa.

  1. package unitat6.apartat1.exemples;
  2. import java.io.File;
  3. public class FileComprovarFitxers {
  4. public static void main(String[] args) {
  5. FileComprovarFitxers programa = new FileComprovarFitxers();
  6. programa.inici();
  7. }
  8. public void inici() {
  9. File temp = new File ("C:/Temp");
  10. File fotos = new File ("C:/Temp/Fotos");
  11. File document = new File ("C:/Temp/Document.txt");
  12. System.out.println(temp.getAbsolutePath() + " existeix? " + temp.exists());
  13. mostrarEstat(fotos);
  14. mostrarEstat(document);
  15. }
  16. public void mostrarEstat(File f) {
  17. System.out.println(f.getAbsolutePath() + " és un fitxer? " + f.isFile());
  18. System.out.println(f.getAbsolutePath() + " és una carpeta? " + f.isDirectory());
  19. }
  20. }

Lectura i modificació de propietats

Quan la ruta amb la qual es treballa correspon a un fitxer o carpeta que realment existeix dins del sistema, hi ha tot un seguit d’informació subministrada pel sistema operatiu que pot resultar útil conèixer: els seus atributs d’accés, la seva mida, la data de modificació, etc. En general, totes les dades mostrades en accedir a les propietats del fitxer. Aquesta informació també pot ser consultada usant els mètodes adients. Entre els més populars n’hi ha els següents:

  • long length() avalua la mida d’un fitxer, en bytes. Aquest mètode només pot ser invocat sobre una ruta que representi un fitxer, en cas contrari no es pot garantir la correctesa del resultat (no es pot considerar com a vàlid en cap cas).
  • long lastModified() avalua la darrera data d’edició de l’element representat per aquesta ruta. El resultat es codifica en un únic número enter on es mesura el nombre de mil·lisegons que han passat des de l’1 de juny de 1970.

De mil·lisegons a una data llegible

La veritat és que, per tal de mostrar dades a l’usuari, treballar amb mil·lisegons per indicar una data no és gaire còmode. Afortunadament, dins el package java.util és possible trobar un tipus compost auxiliar que permet treballar amb dates (igual que File permet treballar amb rutes de fitxers). Es tracta de la classe Date. Per inicialitzar-la, precisament, cal usar com a paràmetre el nombre de mil·lisegons des de l’1 de juny de 1970, en format long.

Date data = new Date(1306751122651L);

No s’entrarà en més detall sobre com funciona aquesta classe. Si voleu, podeu mirar els seus mètodes a la documentació de l’API de Java.

L’exemple següent mostra com funcionen aquests mètodes. Per provar-los, abans creeu un fitxer anomenat “Document.txt” a la carpeta “C:\Temp”. Inicialment, deixeu-lo buit i executeu el programa. Després, amb un editor de text, escriviu qualsevol cosa, deseu els canvis i torneu a executar el programa. Observeu com el resultat és diferent. Fixeu-vos també en l’ús de la classe Date per poder mostrar correctament la data en un format llegible.

  1. package unitat6.apartat1.exemples;
  2. import java.io.File;
  3. import java.util.Date;
  4. public class FileLlegirPropietats {
  5. public static void main(String[] args) {
  6. FileLlegirPropietats programa = new FileLlegirPropietats();
  7. programa.inici();
  8. }
  9. public void inici() {
  10. File document = new File("C:/Temp/Document.txt");
  11. System.out.println(document.getAbsoluteFile());
  12. //S'usa el tipus composta Date per transformar mil·lisegons a data real
  13. Date data = new Date(document.lastModified());
  14. System.out.println("Darrera modificació: " + data);
  15. System.out.println("Mida: " + document.length());
  16. }
  17. }

Gestió de fitxers

De ben segur, el conjunt d’operacions més habituals quan accediu a un sistema de fitxers en treballar en el vostre ordinador són les vinculades a la seva gestió directa: reanomenar fitxers, esborrar-los, copiar-los o moure’ls. Donat el nom d’una ruta, Java també permet realitzar aquestes accions.

  • boolean mkdir() permet crear una carpeta d’acord a la ubicació que indica la ruta. La ruta ha d’indicar el nom d’una carpeta que no existeix en el moment d’invocar el mètode. Concretament, es crea una carpeta amb el nom de la ruta (el darrer element del text), ubicada a la carpeta pare indicada (tot el text anterior). Si s’ha creat correctament, el mètode avalua true. En cas contrari, avalua false. Hi ha diversos motius pels quals pot fallar la creació, però normalment es deurà al fet que la ruta és incorrecta (algun dels elements no existeixen) o la carpeta ja existia.
  • boolean delete() esborra el fitxer o carpeta que indica la ruta. La ruta ha d’indicar el nom d’una carpeta que sí que existeix en el moment d’invocar el mètode. Igual com en l’anterior mètode, avalua true o false segons si l’operació realment s’ha pogut dur a terme. Els motius pels quals pot fallar són similars a l’anterior, si bé en el cas de les carpetes també pot fallar si no està buida. Només es pot esborrar una carpeta usant aquest mètode si dins seu no hi té res (ni altres carpetes ni fitxers).

Per provar l’exemple que es mostra tot seguit de manera que es pugui veure com funcionen aquests mètodes, novament, cal una organització prèvia del sistema de fitxers. Primer, assegureu-vos que a l’arrel de la unitat “C:” no hi ha cap carpeta anomenada “Temp” i executeu el programa. Tot fallarà, ja que les rutes són incorrectes (no existeix “Temp”). Un cop fet, creeu la carpeta “Temp”, i a dins seu creeu un nou document anomenat “Document.txt” (que pot estar buit si voleu). Ara, en executar el programa, s’haurà creat una nova carpeta anomenada “Fotos”. Si sense tocar la carpeta “Temp” executeu el programa per tercer cop, ara tot s’haurà esborrat.

  1. package unitat6.apartat1.exemples;
  2. import java.io.File;
  3. public class FileGestioElements {
  4. public static void main(String[] args) {
  5. FileGestioElements programa = new FileGestioElements();
  6. programa.inici();
  7. }
  8. public void inici() {
  9. File fotos = new File ("C:/Temp/Fotos");
  10. File document = new File ("C:/Temp/Document.txt");
  11. boolean resultat= fotos.mkdir();
  12. System.out.println("Creada carpeta " + fotos.getName() + "? " + resultat);
  13. if (!resultat) {
  14. boolean delCarpeta = fotos.delete();
  15. System.out.println("Esborrada carpeta " + fotos.getName() + "? " + delCarpeta);
  16. boolean delFitxer= document.delete();
  17. System.out.println("Esborrat fitxer " + document.getName() + "? " + delFitxer);
  18. }
  19. }
  20. }

Des del punt de vista d’un sistema operatiu, l’operació de “moure” un fitxer o carpeta no és més que canviar el seu nom, des de la seva ruta original fins a una nova ruta destinació. Per fer això també hi ha un mètode, ja una mica més complex boolean renameTo(File desti).

boolean renameTo(File desti) és un mètode amb un nom una mica enganyós (“reanomenar”, en anglès), ja que la seva funció real no és simplement canviar el nom d’un fitxer o carpeta, sinó canviar la ubicació completa. El mètode s’invoca sobre la variable amb la ruta que es considera el fitxer origen, i el paràmetre d’entrada és la ruta destinació. En aquest cas, el fitxer o carpeta associat a la ruta origen ha d’existir en el moment d’invocar el mètode, però la destinació no. Com en casos anteriors, avalua true o false segons si la tasca s’ha pogut dur a terme correctament o no (la ruta origen i destinació són correctes, no existeix ja un fitxer amb aquest nom a la destinació, etc.). Noteu que, en el cas de carpetes, és possible moure-les tot i que continguin fitxers. Tota l’estructura jeràrquica de carpetes es desplaça.

Un cop més, cal una certa preparació prèvia en l’execució de l’exemple que permet veure com funciona amb més detall aquest mètode. Dins d’una carpeta anomenada “Temp” a la unitat “C:”, creeu una carpeta anomenada “Media” i una altra anomenada “Fotos”. Dins de la carpeta “Fotos”, genereu dos documents (que poden estar buits), anomenats “Document.txt” i “Fotos.txt”. Després d’executar el programa, observeu com la carpeta “Fotos” s’ha mogut i ha canviat de nom, però manté dins seu el fitxer “Fotos.txt”. El fitxer “Document.txt” s’ha mogut fins a la carpeta “Temp”.

  1. package unitat6.apartat1.exemples;
  2. import java.io.File;
  3. public class FileMoure {
  4. public static void main(String[] args) {
  5. FileMoure programa = new FileMoure();
  6. programa.inici();
  7. }
  8. public void inici() {
  9. File origenCarpeta = new File("C:/Temp/Fotos");
  10. File destiCarpeta = new File("C:/Temp/Media/Fotografies");
  11. File origenDocument = new File("C:/Temp/Media/Fotografies/Document.txt");
  12. File destiDocument = new File("C:/Temp/Document.txt");
  13. boolean resultat = origenCarpeta.renameTo(destiCarpeta);
  14. System.out.println("S'ha mogut i reanomenat la carpeta? " + resultat);
  15. resultat = origenDocument.renameTo(destiDocument);
  16. System.out.println("S'ha mogut el document? " + resultat);
  17. }
  18. }

Com es pot veure a l’exemple, aquest mètode també serveix, implícitament, per reanomenar fitxers o carpetes. Si l’element final de les rutes origen i destinació són diferents, el nom de l’element, sigui fitxer o carpeta, canviarà. Per simplement reanomenar un element sense moure’l de lloc, només cal que la seva ruta pare sigui exactament la mateixa. El resultat és que l’element de la ruta origen “es mou” a la mateixa carpeta on està ara, però amb un nom diferent.

Per exemple, el codi següent reanomena un fitxer anomenat “Document.txt”, ubicat a la carpeta “C:/Temp”, a “Reanomenat.txt”:

  1. package unitat6.apartat1.exemples;
  2. import java.io.File;
  3. public class FileReanomenar {
  4. public static void main(String[] args) {
  5. FileReanomenar programa = new FileReanomenar();
  6. programa.inici();
  7. }
  8. public void inici() {
  9. File rutaOrigen = new File("C:/Temp/Document.txt");
  10. //Reanomenar: mateixa ruta pare però diferent nom final
  11. String nouNom = rutaOrigen.getParent() + File.separator + "Reanomenat.txt";
  12. File rutaDesti = new File(nouNom);
  13. rutaOrigen.renameTo(rutaDesti);
  14. }
  15. }

La creació de fitxers de moment es deixarà pendent, ja que està vinculada al tractament de les dades que ha de contenir, i per tant va més enllà de la mera gestió d’una ruta.

Repte 1. Creeu un programa que llegeixi un text pel teclat corresponent a la ruta d’un fitxer existent al vostre ordinador. Canvieu el nom d’aquest fitxer de manera que s’elimini la seva extensió, si en té (per exemple, si el fitxer es diu “Document.txt”, passarà a dir-se “Document”). Per dur a terme aquesta tasca haureu de fer memòria de les transformacions sobre cadenes de text.

Llistat

Finalment, només en el cas de les carpetes, és possible consultar quin és el llistat de fitxers i carpetes que conté.

File[ ] listFiles() avalua un array de File on s’enumeren tots els elements continguts a la carpeta indicada pel text usat en inicialitzar la variable de tipus File. Perquè s’executi correctament, el text de la ruta ha d’indicar forçosament una carpeta. En cada posició d’aquest array hi ha el nom de la ruta de cadascun dels fitxers. La mida de l’array serà igual al nombre d’elements que conté la carpeta. Si la mida és 0, el valor retornat és null i tota operació posterior sobre la variable resultant serà errònia. L’ordre dels elements pot ser qualsevol, no es pot garantir res (al contrari que a l’explorador de fitxers del sistema operatiu, no s’ordena automàticament primer carpetes i després fitxers, o alfabèticament).

La particularitat que potser fa una mica complex aquest mètode, a primera vista, és el fet que avaluï un array de File. Atès que la classe File és un tipus compost, amb vista a treballar amb ell només cal que recordeu com es treballa amb un array de cadenes de text, ja que és el mateix des del punt de vista d’accés a les posicions i invocació de mètodes sobre els valors emmagatzemats.

El millor, però, es veure’n un exemple. Abans d’executar-lo, creeu una carpeta anomenada “Temp” a l’arrel de la unitat “C:”. Dins seu creeu o copieu qualsevol quantitat de carpetes o fitxers.

  1. package unitat6.apartat1.exemples;
  2. import java.io.File;
  3. public class FileLlistarElements {
  4. public static void main(String[] args) {
  5. FileLlistarElements programa = new FileLlistarElements();
  6. programa.inici();
  7. }
  8. public void inici() {
  9. File carpeta = new File("C:/Temp");
  10. File[] arrayElements = carpeta.listFiles();
  11. System.out.println("El contingut de " + carpeta.getAbsolutePath() + " és:");
  12. //Per recórrer un array, s'usa un bucle
  13. for (int i = 0; i < arrayElements.length; i++) {
  14. File f = arrayElements[i];
  15. if (f.isDirectory()) {
  16. System.out.print("[DIR] ");
  17. } else {
  18. System.out.print("[FIT] ");
  19. }
  20. System.out.println(f.getName());
  21. }
  22. }
  23. }

Repte 2. Realitzeu un programa que llegeixi des del teclat el text associat a la ruta a una carpeta existent dins del vostre ordinador. Esborrar tots els elements que hi ha dins, independentment que siguin fitxers o carpetes. Tingueu en compte que per poder eliminar una carpeta cal abans buidar-la de tot el seu contingut (en la qual hi pot haver alhora tant fitxers o carpetes… i així indefinidament fins a arribar a una carpeta que només té fitxers). Pista: Per resoldre aquest problema és molt més senzill plantejar una solució recursiva.

Solució dels reptes proposats

Repte 1

  1. package unitat6.apartat1.reptes;
  2. import java.io.File;
  3. import java.util.Scanner;
  4. public class CanviaNom {
  5. public static void main(String[] args) {
  6. CanviaNom programa = new CanviaNom();
  7. programa.inici();
  8. }
  9. public void inici() {
  10. File rutaFitxer = llegirNomFitxer();
  11. //Cal comprovar si realment existeix i si és un fitxer
  12. if (rutaFitxer.isFile()) {
  13. File novaRuta = treureExtensio(rutaFitxer);
  14. //Es canvia el nom
  15. rutaFitxer.renameTo(novaRuta);
  16. System.out.println("Nom canviat de " + rutaFitxer + " a " + novaRuta);
  17. } else {
  18. System.out.println("Aquest fitxer no existeix!");
  19. }
  20. }
  21. /** Pregunta a l'usuari el nom del fitxer, i d'aquest obté una ruta.
  22.   *
  23.   * @return La ruta associada al text que ha escrit l'usuari.
  24.   */
  25. public File llegirNomFitxer() {
  26. Scanner lector = new Scanner(System.in);
  27. System.out.println("Escriu el nom d'una ruta en un fitxer existent: ");
  28. String nomFitxer = lector.nextLine();
  29. //Fixeu-vos com és possible fer return d'una variable de tipus File,
  30. //igual que es faria per un enter o una cadena de text.
  31. File f = new File(nomFitxer);
  32. return f;
  33. }
  34. /** Donada una ruta, en crea una de nova igual, però sense extensió (.xxx)
  35.   *
  36.   * @param original Ruta original que cal transformar
  37.   * @return La ruta sense extensió
  38.   */
  39. public File treureExtensio(File original) {
  40. String nom = original.getName();
  41. String pare = original.getParent();
  42. //Cerquem el darrer punt, per trobar l'extensió
  43. int posicioPunt = nom.lastIndexOf(".");
  44. if (posicioPunt >= 0) {
  45. //eliminem el que hi ha darrera del punt
  46. String nouNom = nom.substring(0, posicioPunt);
  47. //Es fa el text per a la nova ruta, sense extensió
  48. String nouText = pare + File.separator + nouNom;
  49. File novaRuta = new File(nouText);
  50. return novaRuta;
  51. } else {
  52. //Si no té extensió, es deixa tot igual...
  53. return original;
  54. }
  55. }
  56. }

Repte 2

  1. package unitat6.apartat1.reptes;
  2. import java.io.File;
  3. import java.util.Scanner;
  4. public class NetejarCarpeta {
  5. public static void main(String[] args) {
  6. NetejarCarpeta programa = new NetejarCarpeta();
  7. programa.inici();
  8. }
  9. public void inici() {
  10. File rutaCarpeta = llegirRutaCarpeta();
  11. netejarCarpeta(rutaCarpeta);
  12. }
  13. /** Pregunta a l'usuari el nom de la carpeta, i d'aquest obté una ruta.
  14.   *
  15.   * @return La ruta associada al text que ha escrit l'usuari.
  16.   */
  17. public File llegirRutaCarpeta() {
  18. //Un tipus compost es pot deixar sense inicialitzar posant "null"
  19. File f = null;
  20. boolean preguntar = true;
  21. Scanner lector = new Scanner(System.in);
  22. while (preguntar) {
  23. System.out.println("Escriu el nom d'una ruta en una carpeta: ");
  24. String nomCarpeta = lector.nextLine();
  25. f = new File(nomCarpeta);
  26. if (f.isDirectory()) {
  27. preguntar = false;
  28. } else {
  29. System.out.println("Aquesta carpeta no existeix...");
  30. }
  31. }
  32. return f;
  33. }
  34. /** Donada una ruta associada a una carpeta, esborra tot el seu contingut.
  35.   *
  36.   * @param ruta Ruta de la carpeta que cal netejar
  37.   */
  38. public void netejarCarpeta(File ruta) {
  39. File[] elements = ruta.listFiles();
  40. //Cal mirar tots els elements:
  41. for (int i = 0; i < elements.length; i++) {
  42. if (elements[i].isFile()) {
  43. //Si es un fitxer, s'esborra.
  44. elements[i].delete();
  45. } else if (elements[i].isDirectory()) {
  46. //Si és una carpeta, cal buidar-la primer, o sigui: invocar netejarCarpeta!
  47. netejarCarpeta(elements[i]);
  48. //Un cop buida, es pot esborrar correctament
  49. elements[i].delete();
  50. }
  51. }
  52. }
  53. }
Anar a la pàgina anterior:
Referències
Anar a la pàgina següent:
Activitats