Capítulo 6. Java IO - Ficheiros 1/26
Índice Indice 6.1 - Entrada e saída de dados 6.2 - Ficheiros de texto 6.3 - Ficheiros com formato proprietário 6.4 - A classe File 2/26
Índice 6.1 Entrada e saída de dados 6.1 - Entrada e saída de dados 6.3 -- Ficheiros de texto 6.4 -- Ficheiros com formato proprietário rio 6.5 -- A classe File 3/26
6.1 Entrada e saída de dados Informação binária e textual Normalmente os dados que entram ou saem do ambiente para o programa contêm representação dos dados nos formatos: Streams (Canais) -Binário Informação constituída por zeros e uns que codificam qualquer tipo de dados e têm que ser interpretados pela aplicação -Texto Informação constituída por letras, dígitos, caracteres especiais que no Java correspondem ao tipo primitivo CHAR. Um Stream é um objecto que comunica com um dispositivo físico de leitura ou escrita de dados -Os programas Java lêem e escrevem dados sequencialmente através dos Streams -O Stream é composto por um fluxo infinito e ordenado de bytes sem tamanho pré-definido Permitem obter abstracção de uma fonte genérica ou destino genérico de dados -O Stream disponibiliza sempre os mesmo métodos para qualquer dispositivo Scanner ficheiro = new Scanner(new File( data.txt )); Scanner teclado = new Scanner(System.in); Package java.utils: Classe que lê texto e transforma num tipo apropriado. 4/26
6.1 Entrada e saída de dados Classes utilizadas para entrada e saída de dados Pertencentes ao pacote java.io - InputStream: classe abstracta que lê fluxos binários de informação - OutputStream: classe abstracta que escreve fluxos binários de informação - Reader: a classe abstracta que lê fluxos de texto - Writer: a classe abstracta que escreve fluxos de texto Formato binário Formato texto Pertencentes ao pacote java.utils - Scanner: classe que lê texto e transforma no tipo apropriado (Java 5.0) 5/26
6.1 Entrada e saída de dados Classes utilizadas para entrada e saída de dados Hierarquia de classes pertencentes ao pacote java.io As classes que controlam os Streams dividem-se em dois grandes grupos: -InputStream, OutputStream e suas respectivas subclasses permitem ler e escrever bytes. (formato binário) -Reader, Writer e suas respectivas subclasses permitem ler e escrever caracteres (texto) 6/26
6.1 Entrada e saída de dados Classes utilizadas para entrada e saída de dados Descrição das classes java.io - File: classe que permite gerir ficheiros e directorias -Inputstream: classe abstracta que cria as condições para que as suas subclasses leiam bytes -FileInputStream: classe que permite ler bytes a partir de um ficheiro de texto. -FilterInputStream: classe que rescreve alguns métodos de InputStream de forma a permitir que as suas subclasses façam manipulação de bytes -BufferedInputstream: classe que usa um buffer para ler sequencialmente blocos de bytes a partir de um stream, optimizando o esforço de I/O,permitindo marcar a última posição lida e conseguindo fazer reset -DataInputStream: classe que permite ler bytes sequencialmente a partir de um ficheiro, convertendo-os para os tipos primitivos Java (int, long, float, double, etc.) -Reader: classe asbtracta que cria as condições para que as suas subclasses leiam caracteres; 7/26
6.1 Entrada e saída de dados Classes utilizadas para entrada e saída de dados Descrição das classes java.io -BufferedWriter: classe que permite escrever uma linha de texto, usando o caracter de fim de linha específico da plataforma -BufferedReader: classe que permite ler uma linha do ficheiro de input, optimizando o esforço de I/O -InputStreamReader: classe que lê bytes do InputStream e converte-os para char, seguindo o character set indicado, ou por omissão, o definido no sistema operatiovo -FileReader: classe para ler ficheiros de texto usando o character set definido no sistema operativo, que podemos obter com System.getproperty( file.encoding ) -FileWriter: classe para escrever ficheiros de texto usando o character set definido no sistema operativo. -PrintWriter: classe criada para escrever todos os formatos nativos de dados (int, long, double, etc.) em ficheiros de texto, deforma semelhante à escrita no standard output (consola) 8/26
6.1 Entrada e saída de dados Char Sets padrão do JAVA Dependem do sistema operativo (System.getproperty( file.encoding )). (O Windows usa Cp1252 que é uma versão modificada de ISSO 8859-1) 9/26
Índice 6.2 Ficheiros de texto 6.1 -- Entrada e saí ída de dados 6.2 - Ficheiros de texto 6.3 -- Ficheiros com formato proprietário rio 6.4 -- A classe File 10/26
6.2 Ficheiros de texto em Java Leitura de um char de cada vez Utilização das classes FileReader e FileWriter permitem : -Criar associação entre o objecto usado no programa e o ficheiro (stream). -Trabalhar com caracteres independentemente da plataforma desde que se defina correctamente a propriedade System.getproperty( file.encoding ). public class teste { FileReader (File f); FileReader (String "nome"); FileWriter (File f); FileWriter (String "nome"); FileWriter (String "nome", boolean a); } Construtores aceitam string que corresponde ao nome do ficheiro ou a um objecto da classe File Construtor aceita parâmetro boolean append que se true, efectua append na escrita do ficheiro. Se false cria um novo ficheiro 11/26
6.2 Ficheiros de texto em Java Leitura de um char de cada vez Utilização das classes BufferedReader : Método read() Lê 1 caracter -Devolve o código unicode (nº inteiro) do caracter lido por FileReader(); BufferedReader in = new BufferedReader(new FileReader("Ficheiro01IN.txt")); BufferedWriter out = new BufferedWriter(new FileWriter("Ficheiro01OUT.txt")); while ((n=in.read()!=-1)){ } c=(char) n; out.write(c); in.close(); out.close(); Canal de entrada Canal de Saída Ler enquanto não chegar ao fim do ficheiro (Atenção lança 1 excepção) Converte int em char Escreve o caracter no canal de saída Fechar os canais para libertar recursos -Os caracteres lidos por FileReader ou escritos por FileWriter são empacotados pelas classes BufferedReader e BufferedWriter para aumentar a eficiência 12/26
6.2 Ficheiros de texto em Java Programa que conta o nº de caracteres de um ficheiro de entrada e copia o seu conteudo caracter a caracter para um ficheiro de saída import java.io.*; public class Copia { public static void main (String[] args) throws IOException{ int n, count =0; char c; Obrigatório BufferedReader in = new BufferedReader(new FileReader( d:/ficheiroin.txt")); BufferedWriter out = new BufferedWriter(new FileWriter( d:/ficheiroout.txt")); } } while ((n = in.read())!= -1 )){ c=(char) n; count ++; Não esquecer que BufferedReader devolve o INT referente ao caracter out.write(c); } in.close(); out.close(); System.out.println(count); 13/26
6.2 Ficheiros de texto em Java Programa que conta o nº de caracteres de um ficheiro de entrada e copia o seu conteudo caracter a caracter para um ficheiro de saída Nota: O mesmo programa pode ser realizado recorrendo apenas á classe File. No entanto as classes Buffered são mais eficientes. import java.io.*; public class Copia { public static void main (String[] args) throws IOException{ int n, count =0; char c; } FileReader in = new FileReader( d:/ficheiroin.txt"); FileWriter out = new FileWriter( d:/ficheiroout.txt"); while ((n = in.read())!= -1 ){ c=(char) n; count ++; out.write(c); in.close(); out.close(); System.out.println(count); }} 14/26
6.2 Ficheiros de texto em Java Ler e escrever linhas de texto Para ler um ficheiro de texto linha a linha utilizamos o método readline() da classe BufferedReader() import java.io.*; public class teste1 { public static void main (String[] args) throws IOException{ BufferedReader in = new BufferedReader(new FileReader("D:/FicheiroIN.txt")); PrintWriter out = new PrintWriter(new FileWriter("D:/FicheiroOUT.txt")); String s = in.readline(); while (s!= null) { out.println(s); s = in.readline(); }in.close(); out.close();}} Ler uma linha (método readline()) Repetir enquanto não chegar ao fim do ficheiro Escrever uma linha Para escrever uma linha utilizamos o método println() da classe PrintWriter() O Fim de linha é automático independente da plataforma (\CR\LF em Windows e \LF em UNIX) 15/26
Índice 6.3 Ficheiros com formato proprietário 6.1 -- Entrada e saí ída de dados 6.2 -- Ficheiros de texto 6.3 - Ficheiros com formato proprietário 6.4 -- A classe File 16/26
6.3 Ficheiros com formato proprietário A representação dos caracteres de texto depende da plataforma Existem diferentes convenções para representar caracteres -ASCII, EBCDIC, UNICODE, etc. Existem diferentes convenções para representar o final de linha e final de ficheiro (\CR\LF em Windows e \LF em UNIX) -Nem sempre os ficheiros são portáteis entre diferentes plataformas Como solução o JAVA armazena os caracteres segundo uma norma internacional No entanto este tipo de formato impede a leitura através de um editor de texto comum Normas utlizadas pelo JAVA para representação de dados das variáveis built in -UTF-8 -ISO/IEC 10646 -File System Safe UCS Transformation format (FSS_UTF) -Documento número P316 incluido em X/Open preliminary specification 17/26
6.3 Ficheiros com formato proprietário Leitura e escrita de dados do tipo built in As classes DataInputStream e DataOutputStream permitem ler e escrever dados primitivos do Java num formato portátil e independente da plataforma Array de caracteres é como se fosse uma String 18/26
6.3 Ficheiros com formato proprietário Exemplo: Ficheiro de dados (I) Criar um ficheiro binário de dados que armazena as encomendas feitas a uma loja de ferragens O ficheiro deve ter o seguinte formato e tipos de variáveis: double;int;string numa única linha -Double indica o preço do item -Int indica a quantidade encomendada desse item -String é a descrição do item Para permitir que as descrições tenham tamanho variável utilizamos um caracter separador ; Sequência de dados escrito no ficheiro FicheiroOut.dat 0.05;1;ChaveFendas;2.3;45;Martelo;1.4;98;parafuso;23.0;150;Tinta; preço quantidade descrição... continua Separadores de dados ; O programa irá ler os dados do ficheiro criado anteriormente e imprimi-los 19/26
6.3 Ficheiros com formato proprietário Exemplo: Ficheiro de dados (II) import java.io.*; public class Ficheiro02Cap6 { public static void main (String[] args) throws IOException { // Criar ficheiro com registos cujos campos estão separados por TAB // e pertencem a tipos de dados diferentes DataOutputStream out = new DataOutputStream( new FileOutputStream("d:/FicheiroOut.data")); double [] precos = {0.05,2.3,1.4,23.0}; int [] quantidades = {1,45,98,150}; String[] descricoes = {"ChaveFendas","Martelo","parafuso","Tinta"}; } for (int i=0;i<precos.length;i++){ out.writedouble(precos[i]); out.writechar(';'); // Separador TAB out.writeint(quantidades[i]); out.writechar(';'); // Separador TAB out.writechars(descricoes[i]); // Chars = String out.writechar(';'); // Separador TAB out.close(); Escrita dos dados sequencialmente no ficheiro 20/26
Exemplo: Ficheiro de dados (III) 6.3 Ficheiros com formato proprietário // Ler o ficheiro criado anteriormente DataInputStream in = new DataInputStream( new FileInputStream("d:/FicheiroOut.data")); double preco;int quantidade; String desc; double total = 0.0;char c; try { System.out.println("A sua encomenda foi:"); while (true){ } preco = in.readdouble(); in.readchar(); // Ler o TAB quantidade = in.readint(); in.readchar(); // Ler o TAB //Não existe o método para ler Strings readchars(). Sendo assm, ler tudo o que //são caracteres diferentes de TAB para a descrição desc = ""; while ((c=in.readchar())!= ';') { desc = desc +c ;} System.out.println( quantidade + " unidades de " + desc + " a " + preco + " Euro"); total = total + quantidade * preco; } catch (EOFException e) { System.out.println("Chegou ao final do ficheiro!!!"); Enquanto não existir a excepção EOF (End Of file) Lê os valores tipo Double e Int Atribui-os ás variáveis Lê todos os caracteres que não sejam o separador (Não é possível ler Strings) } System.out.println("Valor total: " + total + " Euro"); in.close();} } 21/26
6.3 Ficheiros com formato proprietário Exemplo: Ficheiro de dados (IV) Comentários: A utilização de um caracter separador de campo (neste caso ; ) só é importante em Strings, pois estas têm tamanhos variáveis e não se conhece a sua dimensão na leitura de um ficheiro neste formato. (A utilização nos outros campos é opcional e está lá para ajudar visualizar a integridade) A leitura do ficheiro termina com uma excepção. Para a evitar pode escrever-se no inicio do ficheiro o número total de registos a ler. -Se antes da String a ler se indicar o seu comprimento evitamos o separador de campo. A ordem de escrita dos dados foi: double ; int ; String. Se a ordem de leitura for diferente (por exemplo int ; double ; string não teremos erro os valores introduzidos não serão correctamente lidos 22/26
Índice 6.4 A classe File 6.1 -- Entrada e saí ída de dados 6.2 -- Ficheiros de texto 6.3 -- Ficheiros com formato proprietário rio 6.4 - A classe File 23/26
6.4 A classe File Utilidades da classe File Não manipula o conteúdo do ficheiro Permite: -Esconder as diferenças entre sistemas operativos -Determinar se um path (caminho) é absoluto ou relativo -Listar o conteúdo de uma directoria -Determinar se há permissões para ler / escrever num ficheiro -Remover um ficheiro e criar uma directoria -Determinar a dimensão de um ficheiro e a data da última alteração 24/26
6.4 A classe File Como usar a classe File A classe File possui um grande número de métodos para obter informações sobre ficheiro ou directoria. Em baixo estão alguns exemplos: 25/26
FIM 26/26