Você está na página 1de 4

Aprendendo a manipular arquivos

Introduo Uma das principais facilidades em Java, comparando com outras linguages de programao, a facilidade na leitura e gravao de arquivos no sistema operacional sem ter de se preocupar com o sistema operacional no qual sua aplicao est rodando. Sendo Java uma linguagem orientada a objetos, nada mais claro que utilizar classes e instncias delas (objetos) para lidar com a saida e entrada de dados (input/output, abreviado: io). O java trata a entrada e sada como fluxos de dados (os to chamados Streams), que voc tem pleno controle sobre eles. Alm disso, a abstrao criada pela linguagem sobre os Streams to grande, que muitas vezes voc est puxando/escrevendo dados em algum Stream, e voc no sabe se eles esto vindo da internet, de um arquivo texto, ou do usurio que est digitando no console. E o mais importante: no faz a menor diferena esta infromao! As classes ligadas a io esto nos pacotes java.io e java.nio (NEW io) e estarei ensinando o bsico das classes responsveis pela leitura e gravao de arquivos de modo no binrio, isto , tratando com Strings e caracteres. Este tutorial explicar passo a passo o que acontece no cdigo, para que voc entenda perfeitamente o que feito, e no decore simplesmente o cdigo. java.io.File Instncias da classe java.io.File representam caminhos (paths) para possveis locais no sistema operacional. Lembre-se que ele apenas representa um arquivo ou diretrio, isto no quer dizer que este caminho exista ou no. Por exemplo, o cdigo a seguir cria uma instncia da classe mencionada, que aponta para /usr/guj/arquivo.txt: File file = new File("/usr/guj/arquivo.txt"); E o cdigo a seguir um caminho para o arquivo arquivo.txt que estara no diretrio atual do sistema e ../arquivo.txt que estar no diretrio pai do atual. Dica: No caso do sistema operacional windows, voc deve usar duplas barras invertidas (\\), j que uma barra invertida apenas considerado escape pelo java! Dica: Em java, voc NO tem como alterar o diretrio atual, por isso pode criar instncias da classe File que apontam para lugares relativos, mas sempre ao diretrio inicial, veja o segundo exemplo abaixo: File noDiretorioAtual = new File("arquivo.txt"); File noDiretorioAnterior = new File("../arquivo.txt"); Existe outras maneiras de criar caminhos relativos a outro caminho, por exemplo: File diretorioRaiz = new File("/"); File arquivo1 = new File(diretorioRaiz,"autoexec.bat"); File arquivo2 = new File(diretorioRaiz,"config.sys"); File diretorioWindows = new File(diretorioRaiz,"windows"); File diretorioWindows2 = new File("/windows/"); File diretorioWindows3 = new File("/windows"); File diretorioWindows4 = new File("c:\\\\windows"); Dica: importante saber que criar um ponteiro para um caminho no sistema operacional no significa criar o arquivo/diretrio. As instanciaes do cdigo acima iriam funcionar mesmo se voc no possusse esses arquivos, porm no iro apontar para um arquivo/diretrio existente.

Um pouco mais da API da classe java.io.File Vamos mostrar um pouco mais da API desta classe, para que voc saiba o que tem disponvel. O primeiro passo descobrir se uma instncia da classe java.io.File aponta para algo que existe, para um diretrio ou arquivo. Os trs mtodos teis nesse momento so: boolean exists(); boolean isDirectory(); boolean isFile(); Outros mtodos que podem ser teis para checar a viabilidade de leitura e gravao so: boolean canRead(); boolean canWrite(); E por fim, alguns mtodos de criao de diretrios, sendo o primeiro o que cria um diretrio e o segundo cria todos os diretrios necessrios para chegar ao caminho apontado pelo objeto. Esses costumam ser muito utilizados: boolean mkdir(); boolean mkdirs(); E outros mtodos comuns so: boolean renameTo(File file); long length(); long lastModified(); boolean delete();

Todos os nomes so autoexplicativos. Qualquer coisa consulte a API da classe File, j que esta ser sua eterna companheira. Algumas pessoas criticam muito essa classe, pois ela deixa voc instanci-la mesmo que ela no represente um arquivo realmente, o que no acontece com as classes a seguir. java.io.FileWriter, java.io.PrintWriter Nesse tutorial no discutiremos sobre arquivos que contm todo o leque de caracteres Unicode e sim arquivos ASCII8, portanto, aqueles que procuram esse tipo de informao, podem dar uma olhada nas classes java.io.FileOutputStream e java.io.OutputStreamWriter que iro criar um Writer para ser encapsulado pelo PrintWriter. Para escrever (e ler de) em um arquivo precisamos saber que Java tem duas camadas de io. Um baixo que le e escreve bytes e um alto que escreve e le caracteres. Vamos estudar os de alto nvel, juntamente com algum encapsulando por cima deste, pois o de alto nvel mexe com chars, e o que encapsula mexe com tudo! O rescritor de caracteres que iremos usar ser uma instncia da classe java.io.FileWriter: FileWriter writer = new FileWriter(new File("saida.txt"),true); FileWriter writer = new FileWriter(new File("saida.txt")); FileWriter writer = new FileWriter("saida.txt",true); FileWriter writer = new FileWriter("saida.txt");

Repare que as duas primeiras linhas obtm o mesmo resultado que a terceira e a quarta, pois existem construtores para objetos do tipo File e String. Dica: Se voc especificar um segundo parmetro como true (primeira e terceira linha), voc pode dizer que deseja adicionar dados a um arquivo que j existe em vez de sobregravar esse arquivo (modo append). Agora j temos uma instncia do "gravador" de caracteres, mas desejamos escrever Strings para o arquivo utilizando uma instancia da classe java.io.PrintWriter que fornece as funcoes print() e println(). PrintWriter saida = new PrintWriter(writer); PrintWriter saida = new PrintWriter(writer,true); Dica: especificando o segundo parmetro como true, os dados sero enviados para o arquivo a toda chamada do mtodo println(), caso contrrio, os dados s so enviados quando voc enviar uma quebra de linha, fechar o arquivo ou mandar ele atualizar as mudanas (modo autoflush). Repare que voc utiliza um objeto da classe java.io.PrintWriter sempre! o System.out uma instncia desta classe, obviamente encapsulando uma outra Stream. Agora voc j pode escrever no arquivo que abriu: saida.println("Camera's ready,"); saida.println("Prepare to flash...."); saida.println("Green Velvet"); Por fim, voc deve fechar o arquivo na ordem contrria que abriu, por segurana: saida.close(); writer.close();

Dica: Nunca se esquea de fechar esses objetos, que liberam recursos para o sistema. Esperar pelo Garbage Collector pode ser a diferena da sua aplicao rodar rpido ou no! java.io.FileReader e java.io.BufferedReader Assim como sobre a escrita, voc deve dar uma lida na API das classes java.io.FileInputStream e java.io.InputStreamWriter para utilizar de mtodos compatveis com caracteres UNICODE. O leito de caracteres que iremos usar durante a leitura ser uma instncia da classe java.io.FileReader: FileReader reader = new FileReader(new File("saida.txt")); FileReader reader = new FileReader("saida.txt"); Como no exemplo de escrita, as duas linhas acima possuem o mesmo resultado. Agora, instanciamos um objeto da classe java.io.BufferedReader que fornece a funcao readLine() e algumas outras, para agilizar o trabalho. BufferedReader leitor = new BufferedReader(reader); BufferedReader leitor = new BufferedReader(reader,1*1024*1024); Dica: voc pode especificar o tamanho do buffer desejado no segundo parmetro. Esse buffer utilizado para minimizar o nmero de pedidos de io para ler blocos maiores do arquivo de uma vez s. Aumentando esse nmero diminui os acessos a disco, mas aumenta o consumo de memria! Agora voc j pode ler: String linha = null; while((linha = leitor.readLine())) {

System.out.println("Linha: " + linha); } E no se esquea de fechar os dois objetos: leitor.close(); reader.close();

java.io.BufferedWriter Voc pode utilizar a classe BufferedWriter para agilizar tambm o processo de gravao: PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("saida.txt"))); PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("saida.txt"),1*1024*1024));

Caso voc no utilize um objeto BufferedWriter no meio, voc ter como resultado uma converso de caracteres em bytes e gravao no arquivo a cada chamada do mtodo print e suas variantes, o que pode ser MUITO custoso. Resumindo Agora voc j consegue ler e gravar arquivos, inclusive otimizando as respectivas operaes. Os prximos passo podem ser: aprender a gravar e ler objetos de um arquivo utilizando as classes ObjectInputStream e ObjectOutputStream, acessar um arquivo de modo aleatrio para leitura e gravao usando a classe RandomAccessFile, parsear a Stream usando (a super lenta) StreamTokenizer, ler e gravar em variaveis em vez de arquivos usando StringReader e StringWriter, utilizar caracteres UNICODE especificando a codificao ao instanciar objetos do tipo InputStreamReader e InputStreamWriter. De exerccio, fica ler um arquivo e gravar uma cpia dele alterando todas as aparies de uma determinada String em outra, da maneira mais eficiente possvel!