Estruturas de Dados - Arquivos

Objetivos da seção

Noção de Stream

stream.gif (3477 bytes)

Montagem de Sequências de Streams

BufferedReader in = new BufferedReader(
                        new FileReader("dados.dat")
                    );
// manipula o stream "in" como veremos adiante

bufferedreader.gif (3741 bytes)

Classe

Direção

Tipo de Informação

Fonte/Destino Processamento
Grava Bytes crus Tipos nativos Objetos Carac-
teres
Arquivo Array de bytes Outro processo Array de carac-
teres
String Bufferi-
zação
Compressão Número
de
Linha
Tokeniza
FileOutputStream X X X X X
ByteArrayOutputStream X X X X X
PipedOutputStream X X X X X
BufferedOutputStream X X X X X
ObjectOutputStream X X
DataOutputStream X X
ZIPOutputStream X X X X X
GZIPOutputStream X X X X X
FileInputStream X X X X X
ByteArrayInputStream X X X X X
PipedInputStream X X X X X
BufferedInputStream X X X X X
ObjectInputStream X X
DataInputStream X X
ZIPInputStream X X X X X
GZIPInputStream X X X X X
RandomAccessFile X X X X
FileWriter X X X
PipedWriter X X X
CharArrayWriter X X X
StringWriter X X X
BufferedWriter X X X
PrintWriter
(imprime formatado)
X X
FileReader X X X
PipedReader X X X
CharArrayReader X X X
StringReader X X X
BufferedReader X X X
LineNumberReader X X X
StreamTokenizer X X X
BufferedReader in = new BufferedReader(
                        new FileReader("dados.dat")
                    );
// manipula o stream "in" como veremos adiante
BufferedOutputStream out = new BufferedOutputStream(
                               new ZipOutputStream(
                                   new FileOutputStream("dados.zip")
                               )
                           );
// manipula o stream "out" como veremos adiante
ObjectOutputStream out = new ObjectOutputStream(
                             new FileOutputStream("agencia.txt"))
                         );
// manipula o stream "out" como veremos adiante

Acesso a Arquivo: Um primeiro Exemplo Simples

import java.io.*;

public class CharCount {
    public static void main(String[] args) {
        if(args.length < 1) {
            System.err.println("Sintaxe: CharCount arq [arq ...]");
            System.exit(1);
        }
        for(int i = 0; i < args.length; i++) {
            try {
                System.out.println(args[i] + ": " + contaCaracteres(args[i]));
            } catch( IOException e ) {
                System.err.println(args[i] + ": Erro: " + e.getMessage());
            }
        }
    }

    static int contaCaracteres(String nomeArquivo) throws IOException {
        BufferedReader in = new BufferedReader(
                                new FileReader(nomeArquivo)
                            );
        int numCarac = 0;
        try {
            while(in.read() >= 0) {
                numCarac++;
            }
        } finally {
            in.close(); // isso é feito mesma que haja exceção
        }        
        return numCarac;
    }
}

Alguns Detalhes sobre o Conceito de Arquivo

Alguns Métodos Disponíveis para Manipular Streams

Serialização de Objetos

package p1.aplic.banco;

import java.util.*;
import java.io.*;
import p1.aplic.geral.*;

/**
 * Classe de agência bancária simples.
 * Nesta versão, há uma única agência. A agência tem uma conta "caixa" para
 * depósitos e saques. A agência pode ser "persistente". Isto significa que
 * tudo que ocorreu de movimentação de contas pode ser gravado em disco
 * para uso posterior ao fechar a agência.
 *
 * @author   Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.1
 * <br>
 * Copyright (C) 1999 Universidade Federal da Paraíba.
 */
public class Agencia {
  protected static boolean    aberto = false;
  protected static Conta      caixa = null;
  protected static Movimento  movimento = null;
  protected static HashMap    titulares = null;
  protected static HashMap    contas = null;

  // várias coisas foram retiradas
  // ...

  /**
   * Fechamento do caixa e gravação dos dados em arquivo.
   * Aborta o programa com mensagem se houver problemas.
   */
   /* deveria usar exceções se der pau aqui, mas vamos poupar os alunos principiantes (usamos isso em programas iniciais) */
  public static void fecharCaixa() {
    // usamos serializacao de objetos para manter os tipos dos objetos
    // se nao fizesse isso, teria problemas em distinguir tipos de contas, de pessoas, ...
    ObjectOutputStream out = null;
    try {
      try {
        out = new ObjectOutputStream(new FileOutputStream(getNomeArquivo()));
        } catch( FileNotFoundException e ) {
          System.err.println("Nao pode criar " + getNomeArquivo());
          System.exit(1);
        }
      List tudo = new ArrayList();  // junta tudo num unico objeto
                                   // para nao perder as ligacoes entre objetos
      tudo.add(titulares);
      tudo.add(contas);
      tudo.add(movimento);
      out.writeObject(tudo);
      out.close();
    } catch(IOException e) {
      System.err.println(e);
      System.exit(1);
    }
  }

  /**
   * Abertura do caixa (da agencia) e leitura dos dados persistentes gravados em arquivo.
     * Aborta o programa com mensagem se houver problemas.
   */
  public static void abrirCaixa() {
    if(aberto) {
      return;
    }
    titulares = new HashMap();
    contas = new HashMap();
    movimento = new Movimento();
    aberto = true; // elimina recursao ao criar a conta caixa
    ObjectInputStream in = null;
    try {
      try {
        in = new ObjectInputStream(new FileInputStream(getNomeArquivo()));
      } catch( FileNotFoundException e ) {
        // nao achar o arquivo significa que estamos começando do zero
        caixa = new ContaCaixa();
        addConta(caixa);
        return;
      }
      List tudo = new ArrayList();
      tudo = (List)in.readObject();
      titulares = (Map)tudo.get(0);
      contas = (HashMap)tudo.get(1);
      movimento = (Movimento)tudo.get(2);
      caixa = localizarConta(0);
      in.close();
    } catch(Exception e) {
      System.err.println(e);
      System.exit(1);
    }
  }

  protected static String getNomeArquivo() {
    return "agencia.dat";
  }
}

Exemplo: Reader e Writer

TITULAR#Ana#12345678901
TITULAR#Joao#30914060506
CONTA#2#12345678901#25/08/2001 18:40#98.76
INICIO_MOVIMENTO
TRANSACAO#1#2#98.76#transferencia para conta 2
FIM_MOVIMENTO
CONTA#1#30914060506#25/08/2001 18:40#1135.8
INICIO_MOVIMENTO
TRANSACAO#25/08/2001 18:40#0#1#1234.56#deposito
TRANSACAO#25/08/2001 18:40#1#2#98.76#transferencia para conta 2
FIM_MOVIMENTO
CONTA#0#0#25/08/2001 18:40#-1234.56
INICIO_MOVIMENTO
TRANSACAO#25/08/2001 18:40#0#1#1234.56#deposito
FIM_MOVIMENTO
INICIO_MOVIMENTO
TRANSACAO#25/08/2001 18:40#0#1#1234.56#deposito
TRANSACAO#25/08/2001 18:40#1#2#98.76#transferencia para conta 2
FIM_MOVIMENTO
TITULAR#Ana#12345678901
TITULAR#Joao#30914060506
CONTA#p1.aplic.banco.ContaSimples#2#12345678901#25/08/2001 18:40#98.76
INICIO_MOVIMENTO
TRANSACAO#25/08/2001 18:40#1#2#98.76#transferencia para conta 2
FIM_MOVIMENTO
CONTA#p1.aplic.banco.ContaSimples#1#30914060506#25/08/2001 18:40#1135.8
INICIO_MOVIMENTO
TRANSACAO#25/08/2001 18:40#0#1#1234.56#deposito
TRANSACAO#25/08/2001 18:40#1#2#98.76#transferencia para conta 2
FIM_MOVIMENTO
CONTA#p1.aplic.banco.ContaCaixa#0#0#25/08/2001 18:40#-1234.56
INICIO_MOVIMENTO
TRANSACAO#25/08/2001 18:40#0#1#1234.56#deposito
FIM_MOVIMENTO
INICIO_MOVIMENTO
TRANSACAO#25/08/2001 18:40#0#1#1234.56#deposito
TRANSACAO#25/08/2001 18:40#1#2#98.76#transferencia para conta 2
FIM_MOVIMENTO
public class Agencia2 extends Agencia {
  /**
   * Separador de campos no arquivo de texto
   */
  private final static String SEPARADOR = "#";
  /**
   * Labels de registros do arquivo de persistencia
   */
  private final static String LABEL_TITULAR = "TITULAR";
  private final static String LABEL_CONTA = "CONTA";
  private final static String LABEL_INICIO_MOVIMENTO = "INICIO_MOVIMENTO";
  private final static String LABEL_FIM_MOVIMENTO = "FIM_MOVIMENTO";
  private final static String LABEL_TRANSACAO = "TRANSACAO";

  /**
   * Fechamento do caixa e gravação dos dados em arquivo.
   * Aborta o programa com mensagem se houver problemas.
   */
  public static void fecharCaixa() {
    PrintWriter out = null;
    try {
      out = new PrintWriter(
              new BufferedWriter(
                new FileWriter(getNomeArquivo())
              )
            );
      gravaTitulares(out);
      // ... grava o resto aqui
      out.close();
    } catch(FileNotFoundException e) {
      fatal("Nao pode criar arquivo " + getNomeArquivo() + ": " + e.getMessage());
    } catch(IOException e) {
      fatal(e.toString());
    }
  }

  private static void gravaTitulares(PrintWriter out) {
    Iterator it;
    it = titulares.values().iterator();
    while(it.hasNext()) {
      Pessoa pessoa = (Pessoa)it.next();
      out.println(LABEL_TITULAR + SEPARADOR +
                  pessoa.getClass().getName() + SEPARADOR +
                  pessoa.getNome() + SEPARADOR +
                  pessoa.getCPF());
    }
  }

  /**
   * Abertura do caixa (da agencia) e leitura dos dados persistentes gravados em arquivo.
   * Aborta o programa com mensagem se houver problemas.
   */
  public static void abrirCaixa() {
    if(aberto) {
      return;
    }
    titulares = new HashMap();
    contas = new HashMap();
    movimento = new Movimento();
    aberto = true; // elimina recursao ao criar a conta caixa
    BufferedReader in = null;
    try {
      in = new BufferedReader(
             new FileReader(getNomeArquivo())
           );
      leInformação(in);
      caixa = localizarConta(0);
      in.close();
    } catch(FileNotFoundException e) {
      // nao achar o arquivo significa que estamos começando do zero
      caixa = new ContaCaixa();
      addConta(caixa);
      return;
    } catch(Exception e) {
      fatal(e.toString());
    }
  }

  private static void leInformação(BufferedReader in) throws Exception {
    String linha;
    while((linha = in.readLine()) != null) {
      StringTokenizer st = new StringTokenizer(linha, SEPARADOR);
      if(!st.hasMoreTokens()) {
        throw new Exception("Erro de sintaxe no arquivo");
      }
      String label = st.nextToken();
      if(label.equals(LABEL_TITULAR)) {
        addTitular(leTitular(st));
      } else if(label.equals(LABEL_CONTA)) {
        // ...
      } else if(label.equals(LABEL_INICIO_MOVIMENTO)) {
        // ...
      } else {
        throw new Exception("Erro de sintaxe no arquivo");
      }
    }
  }

  private static Pessoa leTitular(StringTokenizer st) throws Exception {
    String nome = null;
    String cpf = null;
    try {
      nome = st.nextToken();
      cpf = st.nextToken();
    } catch(NoSuchElementException e) {
      throw new Exception("Erro de sintaxe no arquivo");
    }
    return new Pessoa(nome, cpf);
  }

  protected static String getNomeArquivo() {
    return "agencia.txt";
  }

  /**
   * Erro fatal: imprime erro e cai fora
   */
  private static void fatal(String mensagem) {
    System.err.println(mensagem);
    System.exit(1);
  }
}

Conceito de Entrada/Saída Padrão e Redirecionamento

Palavras Finais

ed-1 programa próxima