Entrada/Saída O que é um Canal Em JAVA, todas os aspectos que se relacionam com as diferentes formas de se realizar a leitura e a escrita de dados a partir de uma fonte e para um destino, são reunidas, e abstraídas, no conceito de canal. Um Canal é uma abstracção que pode representar quer uma fonte genérica de entrada de dados ou um destino genérico para escrita de dados de acesso sequencial e independente de dispositivos físicos concretos, formatos ou até de mecanismos de optimização de leitura e escrita. Em JAVA, existem duas grandes classes de canais, designadamente: Canais de caracteres (canais de texto) Canais de bytes (canais binárias) 2 Classes Base Todos as classes , que implementam formas particulares de Leitura e Escrita em canais, são derivadas de quatro classes abstractas, são elas: Para os canais de bytes: InputStream e OutputStream Para os canais de caracteres: Reader e Writer (associados aos ficheiros) Estas classes sendo abstractas definem o conjunto de métodos que uma qualquer implementação de tais canais deverá concretizar. JAVA oferece serviços básicos de Entrada e Saída através de dois canais associados respectivamente às operações de bytes associada a leitura do teclado ou a e escrita no monitor: System.in: Leitura no teclado System.out: Escrita no monitor 3 Canal de leitura: System.in System.in: É o canal de leitura standard Por omissão lê o teclado Podemos usar System.in de várias maneiras Directamente (acesso básico) Em conjunto com outros canais (acesso combinado) 4 Wrappers & Buffers O package java.io está inteligentemente desenhado. InputStreamReader System.in Algumas das classes funcionam como classes embrulho (wrapper classes) e destinam-se a acrescentar funcionalidade aos canais existentes. Por Exemplo: •InputStreamReader: Permite ler um caracter do teclado sem ser necessário converte-lo manualmente. InputStreamReader System.in (read()) •BufferedReader: Permite ler uma cadeia de caracteres do teclado sem ser necessário converte-lo manualmente BufferedReader (readLine()). 5 Ler do teclado (Java 1.4) try { BufferedReader r = new BufferedReader( new InputStreamReader(System.in)); String s = r.readLine() ; int i = (new Integer(s)).intValue() ; System.out.println(i) ; } catch (IOException e) { } 6 Canais de Bytes ByteArrayInputStream DataInputStream FileInputStream FilterInputStream InputStream SequenceInputStream DataInput BufferedInputStream LineNumberInputStream PushBackInputStream PipedInputStream ObjectInputStream Object ObjectInput StringBufferInputStream ByteArrayOutputStream FileOutputStream OutputStream FilterOutputStream PipedOutputStream ObjectOutputStream BufferedOutputStream DataOutputStream DataOutput PrintStream ObjectOutput RandomAccessFile 7 Canais de Caracteres CharArrayReader InputStreamReader FilterReader Reader FileReader PushBackReader StringReader PipedReader BufferedReader Object LineNumberReader BufferedWriter CharArrayWriter OutputStreamWriter Writer FileWriter FilterWriter PipedWriter PrintWriter StringWriter StreamTokenizer 8 Classe Scanner (JAVA 5.0) A classe Scanner, introduzida com a versão J2SE 5.0, é uma classe nova que permite converter o texto para tipos primitivos. java.util.Scanner O texto pode ser obtido das mais diversas fontes tais como objectos do tipo: Strings InputStream Ficheiros A classe Scanner permite separar o texto em tokens, que são sequências de caracteres separados por delimitadores. Por defeito, os delimitadores são os espaços em branco, tabs e mudanças de linha. 9 Leitura do Teclado Para ler de forma confortável texto do canal de entrada padrão, é preciso criar primeiro um Scanner sobre canal System.in que esta associado ao teclado Scanner sc = new Scanner(System.in); Para cada um dos tipos primitivos há um método correspondente com a assinatura nextXxx() que retorne um valor desse tipo. Se a string não puder ser interpretada como sendo deste tipo, é lançado uma excepção do tipo InputMismatchException. Exemplos de algumas leituras de tokens: String aToken = sc.next() ; //Lê um token int num1 = sc.nextInt() ; //Lê um token inteiro double num2 = sc.nextDouble() ; //Lê um token String linha = sc.nextLine() ; //Lê uma linha real 10 Exemplo: Ler do teclado (Java 5.0) import java.io.*; import java.util.*; class ExScanner{ public static void main(String[] args) { { Scanner scanTeclado = new Scanner(System.in); System.out.println ("Introduza um inteiro"); try { int num = scanTeclado.nextInt(); System.out.println ("Numero introduzido:" + num); } catch (InputMismatchException e) { System.out.println ("Erro na leitura do valor:" + e ); } } } 11 Exemplo: Ler do teclado (Java 5.0) import java.io.*; import java.util.*; class ExScanner{ public static void main(String[] args) { { String str = "Vamos experimentar o scanner"; Scanner scanStr = new Scanner(str); while (scanStr.hasNext()) { System.out.println ("Token:" + scanStr.next()); } } } } 12 Exemplo: Ler do teclado (Java 5.0) import java.io.*; import java.util.*; Ler int (e.g. 3501): Ler float (e.g. Introduziu 123 2,43): Introduziu 2.34 public class ScanConsoleApp{ public static void main (String arg[]) { // Cria um scanner para ler do teclado Scanner scanner = new Scanner (System.in); try { System.out.printf (“Ler int (e.g. %4d): ",3501); int int_val = scanner.nextInt (); System.out.println (" Introduziu " + int_val +"\n"); System.out.printf (“Ler float (e.g. %5.2f): ", 2.43); float float_val = scanner.nextFloat (); System.out.println (" Introduziu " + float_val +"\n"); } catch (InputMismatchException e) { System.out.println (“Erro na leitura do valor:" + e ); } } } 13 Ficheiros Um ficheiro é uma entidade de armazenamento de informação permanente. A manipulação de ficheiros é feita pela utilização de canais que derivam das classes: InputStream; Reader; OutputStream; Writer. Os ficheiros, de acordo com o tipo de informação que podem armazenar, podem ser classificada em: Ficheiros de Texto (Orientado ao caracter) Derivam das classes : Reader e Writer. Fácil de ser lido por humanos com ferramentas simples (type, more, edit, ...). Linhas com comprimento variável. Cada linha termina com uma marca. Exemplo: ficheiro com código-fonte em Java. Ficheiro de Dados (Orientado ao byte) Derivam das classes : InputStream e OutputStream. Apropriado para o processamento por ferramentas automáticas. Armazenamento de tipos primitivos, serialização de objectos, etc. Armazenamento independente da plataforma. 14 A Classe File A classe File representa os ficheiros e directorias de um sistemas de ficheiros. Esta classe define métodos para a realização das operações sobre ficheiros e directorias: listagem de directorias apagar um ficheiro determinar atributos de um ficheiro, alterar o seu nome, etc. Definição: File entFich = new File(cadeia de caracteres); 15 Os métodos da Classe File CONSTRUTORES File(String caminho) construtor de directórios/ficheiros File(String caminho,String nome) construtor com nome separado do caminho File(String directorio, String nome) construtor com directório e nome do ficheiro MÉTODOS boolean canRead() ficheiro/directório pode ser lido boolean canWrite() pode-se gravar no ficheiro/directório boolean delete() apaga ficheiro/directório boolean exists() verifica se ficheiro/directório existem boolean isAbsolute() verifica se caminho é absoluto boolean isDirectory() verifica se objecto é directório boolean isFile() verifica se objecto é ficheiro boolean mKdir() cria directório do objecto boolean mKdirs() cria directórios do caminho boolean renameTo(String novo) muda nome do ficheiro/directório para novo 16 Exemplo: Classe File import java.io.*; class Exemplo { public static void main(String[] args) throws IOException { File meuFicheiro = new File(”dados.dat”); if (meuFicheiro.exists()) System.out.println(“dados.dat existe"); else System.out.println(" dados.dat não existe"); } } Testa a existência do ficheiro “dados.dat” 17 Escrita Ficheiro de Texto Passos necessários para criar um ficheiro de Texto Criar um objecto do tipo File. Permite manipular diversos atributos de um ficheiro. Criar um canal FileWriter ligado ao objecto File. Permite associar um ficheiro de texto a um canal de escrita. Criar um canal tampão BufferedWriter ligado ao objecto FileWriter. Maior eficiência na escrita de um ficheiro. Criar um canal PrintWriter ligado ao objecto BufferedWriter. Permite a utilização dos métodos print e println. 18 Escrita com PrintWriter import java.io.*; public class PrintWriterFileApp{ public static void main (String arg[]) { File file = null; file = new File ("textOutput.txt"); try { FileWriter file_writer = new FileWriter (file); BufferedWriter buf_writer = new BufferedWriter (file_writer); PrintWriter print_writer = new PrintWriter (buf_writer); print_writer.println ("Saida com PrintWriter."); print_writer.println ("tipos primitivos convertidos em strings:"); boolean a_boolean = false; int an_int = 1234567; print_writer.println (a_boolean); print_writer.println (an_int); } catch (IOException ioe){ System.out.println("IO Exception"); } } } 19 Escrita num ficheiro de Texto (formatado) import java.io.*; public class PrintWriterFileApp{ public static void main (String arg[]) { File file = null; file = new File ("textOutput.txt"); Formatter formatter; try { formatter = new Formatter (file); formatter.format ("Saida com PrintWriter. %n"); formatter.format ("tipos primitivos convertidos em strings: %n"); boolean a_boolean = false; int an_int = 1234567; double a_double = -4.297e-15; formatter.format ("boolean = %9b %n", a_boolean); formatter.format ("int = %9d %n", an_int); formatter.format ("double = %9.2e %n", a_double); formatter.flush (); formatter.close (); } catch (IOException ioe){ System.out.println("IO Exception"); } }} 20 Escrita num ficheiro de Texto (formatado) formatter.format ("Saida com PrintWriter. %n"); %n –> mudança de linha Ficheiro textOutput.txt : Saida com PrintWriter. Tipos primitivos convertidos em strings: boolean = false int = 1234567 double = -4.30e-15 21 Leitura Ficheiro de Texto Leitura com Scanner Leitura com File Reader Criar um objecto do tipo File Permite manipular diversos atributos de um ficheiro. Criar um canal FileReader ligado ao objecto do tipo File Permite a leitura de um ficheiro escrito em formato ASCII. Criar um canal tampão BufferedReader ligado objecto do tipo FileReader Maior eficiência na leitura de um ficheiro. 22 Leitura com Scanner import java.io.*; import java.util.*; public class LeituraFicheiro { public static void main (String arg[]) { Ficheiro textInput.txt: 123 Primeiro 234 Segundo Saida: File file = new File ("textInput.txt"); Numero inteiro lido: 123 Scanner scanner = null; Primeiro try { Numero inteiro lido: 234 scanner = new Scanner (file); Segundo while( scanner.hasNext()) Finished executing { int num = scanner.nextInt(); System.out.println ("Numero inteiro lido: " +num); System.out.println (scanner.next()); } } catch (InputMismatchException e) { System.out.println ("Mismatch exception:" + e ); } catch (FileNotFoundException e) { System.out.println ("Ficheiro não encontrado!"); System.exit (0); } }} 23 Leitura com FileReader (Ex.1) Le um ficheiro de texto. import java.io.*; import java.util.*; Envia para o ecrã cada linha lida. class LeFicheiro { public static void main(String[] args) throws IOException { String linha; File f; FileReader fich; BufferedReader entrada = null; 24 Leitura com FileReader (Ex.1) try { f = new File("meuFich.dat"); fich = new FileReader(f); entrada = new BufferedReader(fich); do { linha = entrada.readLine(); if (linha != null ) System.out.println(linha); } while (linha != null); } 25 Leitura com FileReader (Ex1) catch ( IOException e) { System.out.println("Erro de I/O."); System.out.print(e); } finally { System.out.println("fim do programa."); if (entrada != null) entrada.close(); } } } 26 Exemplo 2 import java.io.*; class ContaDigitoCaracter{ public static void main(String[] args) throws IOException { int proxValor, numMaius=0, numMinu=0, numDigitos=0, numOutros=0; char proxCar; Lê um ficheiro e retorna os números de: String nomeFicheiro; digitos; letras maisculas; letras // Obtem ficheiro do utilizar System.out.print(“Nome do ficheiro: "); nomeFicheiro = Le.umaString(); File fich= new File(nomeFicheiro); minusculas e outros caracteres // testa leitura if (fich.exists() && fich.canRead()) { // Cria os canais BufferedReader fichEnt = new BufferedReader(new FileReader(fich)); 27 Exemplo2 // Le do ficheiro proxValor = fichEnt.read(); while (proxValor != -1){ proxCar = (char) proxValor; if (Character.isDigit(proxCar)){ numDigitos++; } else if (Character.isUpperCase(proxCar)){ numMaius++; } else if (Character.isLowerCase(proxCar)){ numMinu++; } else { numOutros++; } proxValor = fichEnt.read(); } 28 Exemplo2 Nome do Ficheiro: ContaCar.java Numero de digitos: 7 Numero de letras maisculas: 96 Numero de letras minusculas: 1001 Numero de outros caracteres: 832 //fecha canal fichEnt.close(); //Mostra resultados System.out.print(“Numero de digitos: “); System.out.println( numDigitos); System.out.print(“Numero de letras maisculas: “); System.out.println( numMaius); System.out.print(“Numero de letras minusculas: “); System.out.println( numMinu); System.out.print(“Numero de outros caracteres: “); System.out.println( numOutros); } else { System.out.print(“não é possível ler ficheiro: “); System.out.println(nomeEntrada); } } } 29 Exemplo3 - Ficheiro Texto Leitura de um Ficheiro e separação de dados Ficheiro: accoes.dat ACME 6/1/96 50 46.5 49.75 SP500 6/2/96 124 122 123.5 DWMI 6/1/96 24.5 22.25 24.5 Pretende-se manipular um ficheiro (accoes.dat), no qual cada linha contem o registo de uma sessão da bolsa sobre um grupo de acções: Nome da acção, data do registo, valor mais alto obtido, valor mais baixo obtido, valor de fecho. 30 Exemplo3 - Ficheiro Texto Leitura de um Ficheiro e separação de dados import java.io.*; import java.util.*; public class stock_data { public static void main(String args[]) { String nome_accao; Date data_registo; float valor_alto, valor_baixo, valor_fecho; try { String linha_str; int linha_numero; File fich= new File("accoes.dat"); // Cria os canais BufferedReader fichEnt = new BufferedReader(new FileReader(fich)); 31 Exemplo3 - Ficheiro Texto Leitura de um Ficheiro e separação de dados(cont.) while ((linha_str = fichEnt.readLine()) != null) { StringTokenizer st = new StringTokenizer(linha_str); // extrai tokens e os converte para os tipos apropriados nome_accao data_registo valor_alto valor_baixo valor_fecho = = = = = st.nextToken(); new Date(st.nextToken()); Float.valueOf(st.nextToken()).floatValue(); Float.valueOf(st.nextToken()).floatValue(); Float.valueOf(st.nextToken()).floatValue(); 32 Exemplo3 - Ficheiro Texto Leitura de um Ficheiro e separação de dados (cont.) // mostra resultado System.out.println("nome da Accao :" + nome_accao); System.out.println("Data Registo :" + data_registo); System.out.println("valores: Alto:" + valor_alto + " Baixo:" + valor_baixo + " Fecho:" + valor_fecho); System.out.println(); } fichEnt.close(); } catch (IOException e) { System.out.println("Erro I/O: " + e); } } } 33