Neste artigo vamos abordar uma matéria que, a nosso ver, é bastante interessante e importante no mundo da programação: o input/output, neste caso aplicado a Java.
Iremos começar com manipulação de ficheiros e directorias. Vamos ver a seguinte classe Java, onde são demostradas as principais funções da classe File
, que é a utilizada para realizar a manipulação. Em seguida vamos explicar o que cada linha faz.
import java.io.*; public class JavaFile { public static void main(String args[]) { File file = new File("C:\\file.txt"); System.out.println( file.getName() ); file.setReadOnly(); System.out.println( file.isHidden() ); System.out.println( file.canRead() ); System.out.println( file.canWrite() ); file.renameTo( new File("C:\\Ficheiro.txt") ); try { if( !file.exists() ) { file.createNewFile(); } } catch(Exception e){ System.out.println(e.getMessage()); } if( file.isDirectory() ) { System.out.println("Directoria"); } else if( file.isFile() ){ System.out.println("Ficheiro"); } File [] roots = file.listRoots( ); for (int i = 0; i < roots.length; i++) { System.out.println (roots[i] ); } file.delete(); } }
Como podemos ver na linha 5 é instanciado um objecto File
que representa o caminho (path) para um possível local do sistema operativo, é bom lembrar que apenas representa um ficheiro ou directoria, não pressupondo que o caminho exista realmente. Neste caso o caminho é o C:\\file.txt
, que aponta para o ficheiro file.txt
na directoria C:
. Também poderia apontar apenas para uma directoria e não para uma ficheiro, como é o caso.
Na linha 7 podemos ver o método getName()
que permite obter o nome do ficheiro ou directoria representada pelo File
.
Esta classe permite também dar atributos a ficheiros ou directorias, como é o caso do método setReadOnly()
, que dá ao ficheiro ou directoria o atributo de apenas poder ser lido e não escrito, tal como esta representado na linha 9.
A classe File
permite também verificar atributos e, para isso, podemos usar os métodos isHidden()
que verifica se o ficheiro ou directoria se encontra oculto(a) (linha 11), canRead()
que verifica se é possível ler o ficheiro ou directoria (linha 12) e o método canWrite()
que verifica se é possível escrever no ficheiro ou directoria (linha 13).
O método renameTo()
na linha 15 permite renomear um ficheiro ou directoria, mas para além disso permite também mover ficheiros e directorias, bastando para isso dar um caminho diferente no novo nome a dar, o que não é o caso neste exemplo.
Os métodos exists()
e createNewFile()
(linha 18 e linha 19), são dois métodos muito importantes na manipulação de ficheiros e directorias. O método exists()
permite verificar se o ficheiro ou directoria representados no File
existe. O método createNewFile()
cria um novo ficheiro com o caminho representado. Neste caso iria criar o ficheiro file.txt
na directoria C:
.
Embora aqui não presente, também temos os métodos mkdir()
e mkdirs()
que têm a mesma funcionalidade que o método createNewFile()
, mas neste caso é criada uma directoria. A diferença do mkdir()
para o mkdirs()
é basicamente que o método mkdir()
apenas cria uma directoria num caminho já existem, ou seja, por exemplo, o seguinte caminho C:\Programas\
o mkdir()
poderia criar directorias dentro da directoria Programas
apenas e só se a referida directoria já existisse previamente. Já o mkdirs()
permite criar toda a árvore de directorias, mesmo se esta não existisse.
Nas linhas 26 e 29 podemos ver os métodos isDirectory()
e isFile()
que verificam respectivamente se o caminho dado é um directorio ou um ficheiro.
Na linha 33 temos o método listRoots()
. Trata-se de um método bastante útil, nomeadamente em sistemas Windows, visto que ele devolve um array com todas a drives ou raízes do sistema operativo, por exemplo A:
, C:
, D:
, E:
, etc… Já em sistemas GNU/Linux o conteúdo do array será apenas /
, visto ser a raiz do sistema.
Para terminhar esta parte do artigo, temos na linha 39 o método delete()
, que como o proprio nome indica, permite eliminar o ficheiro ou directoria representado pelo File
.
Depois de terminado o estudo sobre a manipulação de ficheiros, vamos agora passar à escrita dos mesmos, observando o seguinte código.
import java.io.*; public class FileWrite { public static void main(String args[]) { try{ PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("C:\\file.txt",true))); out.println("Java Input/Output"); out.println(System.getProperty("os.name").toString()); out.println(System.getProperty("user.name").toString()); out.println("Fim"); out.println(); out.close(); } catch(IOException e){ System.out.println(e.getMessage()); } } }
Após executar esta aplicação será criado um ficheiro de texo em C:\\
(nos sistemas Windows, para outros sistemas operativos bastará mudar o destino), com conteúdo semelhante a este:
Java Input/Output Windows XP Magician Fim
Vamos agora analisar o código de forma a compreender o objectivo de cada linha.
Na linha 6 podemos ver a o objecto out
a ser instanciado. Esta é uma instanciação um pouco complexa, mas tem a sua razão de ser. Segundo alguns teste já feitos esta instanciação é a forma
mais simples e com melhor rendimento de escrever num ficheiro. Vamos agora atentar em alguns detalhes. Na última parte da instância new FileWriter("C:\\file.txt",true)
podemos ver que para além de termos como argumento o nome do ficheiro, temos também um argumento boolean
. Este é sem duvida um argumento muito importante pois quando colocado true
diz ao programa que deve escrever no ficheiro, com a particularidade de não apagar nenhum do seu conteúdo anterior, ou seja, o programa não escreverá por cima do que já la se encontra. No caso de se colocar como argumento um boolean
false
, ou apenas o nome do ficheiro, o programa cada vez que for executado vai reescrever o ficheiro a partir do início, apagando toda a informação já la contida.
Após executar o programa duas vezes com o argumento true
, o conteúdo do ficheiro irá aparecer duas vezes. O conteúdo do ficheiro só aparecerá uma vez, após executar o programa duas vezes, com o argumento false
ou sem o argumento.
Na linha 8, bem como na 9, 10, 11 e 12, podemos ver a utilização do método println()
sobre o objecto out
. Este método vai permitir escrever uma linha no ficheiro. Existem outros métodos como o print()
e write()
com funcionalidade idênticas, embora menos utilizados ao nível da escrita de ficheiros de texto.
Por fim temos o método close()
que irá “fechar” o ficheiro, algo que deve ser sempre executado assim que se termina a escrita num ficheiro. É assim terminada a ligação entre o ficheiro e o programa. É, portanto, um passo fulcral, visto que caso não executado, poderá deitar a perder o conteúdo do ficheiro.
Agora que já sabemos como escrever em ficheiros apenas falta a leitura dos mesmos. Para isso vamos começar por observar o seguinte código.
import java.io.*; public class FileRead { public static void main(String args[]) { try { BufferedReader leitor = new BufferedReader(new FileReader("C:\\file.txt")); String linha = ""; linha = leitor.readLine(); while(linha != null) { System.out.println(linha); linha = leitor.readLine(); } leitor.close(); } catch(IOException e){ System.out.println(e.getMessage()); } } }
De uma forma resumida, o que este código vai fazer é simplesmente ir ao ficheiro file.txt
, ler linha a linha e imprimir na consola. Como podemos ver na linha 6 é criado um objecto BufferedReader
que, através de um objecto FileReader
, irá aceder ao ficheiro file.txt
. Na linha 7 vamos criar a variável linha
, do tipo String
, inicializando-a como string vazia (""
). Em seguida na, linha 8, vamos ler a primeira linha do ficheiro e vamos colocar o conteúdo dessa linha na variável linha
, sob forma de String
.
Nas linhas 9–12 é feito um ciclo para ler todas as linhas do ficheiro, cada vez que o ciclo da uma volta, é impreso o valor da linha anterior e lido a linha seguinte, até não existir mais linhas no ficheiro. Finda a leitura, a ligação ao ficheiro é terminada. O resultado final será exactamente o conteúdo do ficheiro.
Após estas três partes do artigo o leitor já conseguirá realizar as principais funções de IO em Java. Existe um sem numero de outras formas de fazer o que foi aqui demonstrado, bem como um sem número de outras coisas de se pode fazer com Java IO.