Streams

Propaganda
Arquivos e Streams
Porto Alegre
Alegre,, novembro de 2006
Adaptado das aulas dos Profs: Isabel Manssour, Luciana Nedel, Bernardo Copstein e Júlio Machado
Roteiro
n
Introdução a Arquivos
n
Streams
n
Serialização
n
Arquivos de Acesso Randômico
n
Exercícios
Introdução a Arquivos
n
Armazenamento
n
Dados em vetores, listas e variáveis
n
Arquivos
n
n
n
n
Perdidos quando acaba a execução do programa
Armazenamento permanente de dados
Dados persistentes
Dispositivos de armazenamento secundários
n
n
Armazenam arquivos
Discos magnéticos, discos ópticos, fitas magnéticas
‹# ›
Introdução a Arquivos
n
Hierarquia de dados
n
Campo (Field)
n
n
n
Conjunto de caracteres com o mesmo significado
Exemplo: nome
Registro (Record)
Conjunto de campos relacionados
Exemplo: nome, endereço, idade, telefone de uma
pessoa
n Representado por uma instância de uma classe
n
n
Introdução a Arquivos
n
Hierarquia de dados
n
Arquivo (File)
n
n
n
Conjunto de registros relacionados
Exemplo: informações sobre um grupo de pessoas
Base de dados (Database)
n
n
Conjunto de arquivos relacionados
Exemplo: folha de pagamento, controle de estoque,
controle de contas
Introdução a Arquivos
Ficha
Nome: ____
Endereço: _____
Telefone: ______
CIC: ______
RG: _______
Registro
Campos
Campo
Registro
Endereço
Telefone
CIC
RG
Ana Silva
Nome
Andradas 34
332.56.35
345.565/9
271646252
João Neto
Siqueira 34
353.46.54
454.567/8
456546568
Maria Santos Ipiranga 67
223.66.51
028.480/8
873260269
:
:
:
:
:
Arquivo
‹# ›
Introdução a Arquivos
n
Chave primária
Apresenta um valor diferente para cada
registro do arquivo
n A partir de uma chave primária identifica-se
um único registro no arquivo
n
Introdução a Arquivos
n
Chave de acesso
Facilita a recuperação de registros
Usada para identificar o registro desejado em
uma operação de acesso a um arquivo
n Um campo é escolhido como chave de acesso
n
n
Identifica um registro (entidade única dentre todos
os outros registros)
n Exemplo: número do CPF
n
Introdução a Arquivos
n
Chave de ordenação
n
n
É a chave primária usada para estabelecer
a seqüência na qual devem ser dispostos
os registros de um arquivo
Chave secundária
n
Difere de uma chave primária pela
possibilidade de ter valores iguais para as
chaves
‹# ›
Introdução a Arquivos
n
Arquivo seqüencial
Todos os registros estão organizados na forma
de uma lista, um depois do outro
n Os registros podem estar dispostos
ordenadamente, obedecendo a seqüência
determinada pela chave primária
n É possível incluir, excluir, alterar e consultar os
registros
n
Introdução a Arquivos
n
Arquivo seqüencial
n
Exemplo:
Nome: João
End: ____
Fone: ____
Válido: V
Nome: Maria
End: ____
Fone: ____
Nome: José
End: ____
Fone: ____
Nome: Ana
End: ____
Fone: ____
Nome: Paulo
E
End: ____
O
Fone: ____
Válido: V
Válido: V
Válido: V
Válido: V
F
Todos os registros possuem o mesmo tamanho e são
armazenados seqüencialmente na memória
Introdução a Arquivos
n
Arquivo seqüencial
n
Inclusão no final
Nome: João
End: ____
Fone: ____
Válido: V
Nome: Maria Nome: José
End: ____
End: ____
Fone: ____ Fone: ____
Nome: Ana
End: ____
Fone: ____
Nome: Paulo Nome: Rita
End: ____
End: ____
Fone: ____ Fone: ____
Válido: V
Válido: V
Válido: V
Válido: V
Válido: V
E
O
F
‹# ›
Introdução a Arquivos
n
Arquivo seqüencial
n
Exclusão lógica: Maria
Nome: João
End: ____
Fone: ____
Válido: V
n
Nome: Maria Nome: José
End: ____
End: ____
Fone: ____ Fone: ____
Nome: Ana
End: ____
Fone: ____
Nome: Paulo Nome: Rita
End: ____
End: ____
Fone: ____ Fone: ____
Válido: F
Válido: V
Válido: V
Válido: V
Válido: V
E
O
F
Exclusão física
Nome: João
End: ____
Fone: ____
Válido: V
Duplica os
registros
Nome: Maria
End: ____
Fone: ____
Válido: V
Nome: José
End: ____
Fone: ____
Válido: V
Nome: Ana
End: ____
Fone: ____
Válido: V
Nome: Paulo
End: ____
Fone: ____
Válido: V
Nome: Rita
End: ____
Fone: ____
Válido: V
E
O
F
Nome: João
End: ____
Fone: ____
Válido: V
Nome: José
End: ____
Fone: ____
Válido: V
Nome: Ana
End: ____
Fone: ____
Válido: V
Nome: Paulo
End: ____
Fone: ____
Válido: V
Nome: Rita
End: ____
Fone: ____
Válido: V
E
O
F
Introdução a Arquivos
n
Arquivo seqüencial
n
Pesquisa seqüencial
Nome: João
End: ____
Fone: ____
Válido: V
n
Nome: Maria Nome: José
End: ____
End: ____
Fone: ____ Fone: ____
Nome: Ana
End: ____
Fone: ____
Nome: Paulo Nome: Rita
End: ____
End: ____
Fone: ____ Fone: ____
Válido: V
Válido: V
Válido: V
Válido: V
Válido: V
E
O
F
Acesso direto
n
Contar os bytes...
Introdução a Arquivos
n
Arquivo de índice
Consiste em um arquivo que guarda o campo
chave e a posição do registro no disco
n Exemplo:
n
E100
E101
Nome: João
End: ____
Fone: ____
Válido: V
Nome: Maria Nome: José
End: ____
End: ____
Fone: ____ Fone: ____
Válido: F
E102
E103
Nome: Ana
End: ____
Fone: ____
Válido: V
Válido: V
Arquivo de Dados
E104
E105
Nome: Paulo Nome: Rita
End: ____
End: ____
Fone: ____ Fone: ____
Válido: V
Válido: V
E
O
F
E
Chave: Ana
Chave: João
Chave: José
Chave: Maria Chave: Paulo Chave: Rita
O
Posição: E103 Posição: E100 Posição: E102 Posição: E101 Posição: E104 Posição: E105
F
Arquivo de Índice
‹# ›
Introdução a Arquivos
n
Arquivos de índice
n
n
Permitem o acesso rápido às dados
Vários podem ser criados
Índice por nome
Índice por idade
n Índice por telefone
n ...
n
n
Introdução a Arquivos
n
Arquivo binário
n
n
Os dados são armazenados
em disco utilizando o
mesmo formato binário de
armazenamento em
memória
Arquivo texto
n
Os dados são armazenados
em disco em registros de
um único byte (um caractere
ASCII)
Introdução a Arquivos
n
Programas que trabalham com arquivos
devem permitir
Incluir, excluir, consultar e alterar registros
Incluir novos campos nos registros
n Excluir campos dos registros
n
n
n
Todas estas tarefas exigem muita
programação
‹# ›
Introdução a Arquivos
n
Portanto, para facilitar este gerenciamento
foi criado o SGBD - Sistema Gerenciador
de Banco de Dados
Ferramenta cujo objetivo principal é gerenciar
o acesso e a correta manutenção dos dados
armazenados no banco de dados
n Exemplos: Oracle, Access, Sybase, etc.
n
Roteiro
n
Introdução a Arquivos
n
Streams
n
Serialização
n
Arquivos de Acesso Randômico
n
Exercícios
Streams
n
Criar um bom sistema de E/S é uma das
tarefas mais delicadas na programação
Existem diversas abordagens diferentes
Deve-se tratar várias origens e destinos para os
dados (console, disco, impressora, conexão de
rede,...).
n Existem vários modos de acesso (seqüencial,
randômico, com ou sem buffer, por linhas, por
palavras, binário ou caractere,...)
n
n
‹# ›
Streams
n
Java provê uma biblioteca com muitas classes,
cada uma com um propósito diferente
n
Pacote java.io.*
Streams
n
Stream (fluxo) de E/S
n
Gera o caminho por meio do qual os programas
podem enviar uma seqüência de bytes de uma
fonte até
um destino Programa escreve i n f o r m a ç ã o Destino
um stream
Fonte
informação
um stream
n
n
lê
Programa
Normalmente associados a arquivos
Teclado, mouse, memória, vídeo ou impressora
também podem ser uma fonte ou destino
Streams
Streams (fluxo de bytes)
Impressora
Teclado
Monitor
Aplicação
Java
HD
Mouse
‹# ›
Streams
n
Java
Cada arquivo é um fluxo seqüencial de bytes
A ca b a co m u m “m a rca d o r d e fim d o a rq u ivo ” (endof-file), ou
n Acaba em um número específico de bytes
(registrado em uma estrutura de dados mantida
pelo sistema)
n
n
Programa que processa fluxo de bytes recebe
uma indicação quando alcança o final do fluxo
n Abertura de um arquivo em Java
n
n
Cria um objeto e associa um fluxo de bytes a este
objeto
Streams
n
Objetos stream automaticamente criados
quando um programa java é executado:
System.in - standard input (inserção de bytes
via teclado)
n System.out - standard output (saída de dados
na tela)
n System.err - standard error (saída a
mensagens de erro na tela)
n Podem ser redirecionados para disco, por
exemplo
n Fornecem canais de comunicação
n
Streams
n
Streams
Permite a comunicação de programas Java
com o meio externo (além da console e dos
componentes para interfaces gráficas)
n Lidam apenas com entrada ou saída de bytes
n
n
Fluxos de byte: tratam entrada ou saída de 8 bits
n
Fluxos de caractere: tratam entrada ou saída de
16 bits
n
n
Classes InputStream, OutputStream
Classes Reader, Writer
‹# ›
Streams
n
Fluxos de byte
Streams
n
Fluxos de bytes:
n
São subclasses de InputStream e
OutputStream
n
n
n
Classes abstratas
Definem métodos para entrada e saída
Estas classes, bem como as várias classes para
trabalhar com arquivos, estão no pacote
java.io
Streams
n
Arquivos são abertos criando-se objetos das
classes FileInputStream (para leitura) e
FileOutputStream (para escrita)
n
Exemplo:
FileInputStream a = new FileInputStream ("arq.dat");
FileOutputStream b = new FileOutputStream("c:/java/arq.dat");
Ao criar o arquivo, um stream é associado ao
objeto
n Estas classes possuem apenas os métodos
read/write para ler e gravar bytes de arquivos de
entrada/saída (arquivos binários)
n
‹# ›
Streams
n
Leitura de dados diretamente como bytes
n
n
Rápido mas complicado
Usualmente lê-se dados como agregados de
bytes que formam um int, um double, etc.
Streams
n
Para ler/gravar tipos de dados mais elaborados é
necessário associar filtros aos Streams
n
n
Java oferece diversas classes filtro para serem conectadas
no stream básico
Classes filtro para realizar E/S de tipos de dados primitivos
n
n
DataInputStream e DataOutputStream
Usados junto com as classes de fluxo de arquivo
Arquivo
Apenas métodos read/write
para ler e gravar bytes
FileInputStream
FileOutputStream
DataInputStream
DataOutputStream
Memória
Permitem ler/gravar tipos de
dados mais elaborados, pois
possuem métodos para E/S
de inteiros, reais etc.
Streams
Aplicação Java
(int, float, ...)
Aplicação Java
(int, float, ...)
Streams
(fluxo de bytes)
Streams
(fluxo de bytes)
HD
(arquivo)
HD
(arquivo)
‹# ›
Streams
n
n
As classes DataInputStream/DataOutputStream
possuem métodos para E/S de tipos de dados
primitivos, tais como inteiros e reais
E/S de dados binários
n
DataInputStream
n
n
n
DataOutputStream
n
n
n
Lê bytes de InputStream
Métodos read, readByte, readChar, readDouble,
readUnsignedShort...
Escreve bytes em OutputStream
Métodos write, writeChar, writeChars, writeBoolean,
writeInt...
Exemplo:
Streams
import java.io.*;
class StreamTest{
public void gravaDados( ){
try{
FileOutputStream fos=new FileOutputStream("dados.dat");
DataOutputStream dos = new DataOutputStream(fos);
dos.writeInt(10);
dos.writeInt(20);
dos.writeDouble(3.14);
dos.writeLong(123456789);
dos.close();
}
catch(IOException e){
System.out.println("File error: "+e.getMessage());
}
}
(continua...)
Streams
(...continua)
public void leDados(){
try{
FileInputStream fis = new FileInputStream("dados.dat");
DataInputStream dis = new DataInputStream(fis);
System.out.println("Dados: "
+dis.readInt()+":"+dis.readInt()+":"
+dis.readDouble()+":"
+dis.readLong());
dis.close();
}
catch(IOException e){
System.out.println("File error: "+e.getMessage());
}
}
(continua...)
‹# ›
Streams
(...continua)
public static void main(String args[]){
StreamTest st = new StreamTest();
st.gravaDados();
st.leDados();
}
}
Roteiro
n
Introdução a Arquivos
n
Streams
n
Serialização
n
Arquivos de Acesso Randômico
n
Exercícios
Serialização
n
Podemos armazenar os dados em arquivos
ou em bancos de dados
n
Esse tipo de procedimento não apresenta
problemas quando os dados a serem
gravados são tipos primitivos, mas os
problemas começam quando se tenta
armazenar referências para objetos
‹# ›
Serialização
n
Normalmente, para armazenar uma estrutura de
memória que se utilize de referências (como por
exemplo, estruturas encadeadas) é preciso
armazenar todos os tipos de dados primitivos
iso la d a m e n te ju n ta m e n te co m a lg u m tip o d e “ch a ve
d e a ce sso ”.
n
Não é possível armazenar diretamente referências
porque as mesmas são baseadas em endereços
de memória e a própria ordem em que se carrega
os objetos pode implicar em que eles sejam
alocados em posições de memória diferentes
daquelas que ocupavam quando foram gravados.
Serialização
n
Pior, os objetos podem ser gravados por um
programa e lidos por outro. Neste caso
certamente os endereços de memória serão
diferentes.
n
A solução é serializar os objetos, ou seja,
gravá-los de maneira que na hora de
restaurá-los seja possível recriar as
instâncias e reconectá-las da maneira
correta.
Serialização
n
A maneira de fazer isso é implementar a
interface Serializable
n
n
n
Esta interface não tem métodos
Serve apenas para indicar que os atributos deste
objeto podem ser serializados e deserializados
A leitura/gravação de objetos serializáveis é
feita através das classes ObjectInputStream
e ObjectOutputStream.
‹# ›
Serialização
n Passo
1: declarar o objeto como
serializável:
import java.io.Serializable;
class Dados implements Serializable{
private int dado;
public Dados(int n){ dado = n; }
public void imp(){
System.out.println("Dado = "+dado);
}
}
Serialização
n
Passo 2: gravar o objeto usando
ObjectOutputStream:
Dados dado = new Dado(20);
try{
FileOutputStream os = new FileOutputStream(“teste");
ObjectOutputStream oarq = new ObjectOutputStream(os);
oarq.writeObject(dado);
oarq.close();
}catch(IOException e){
System.out.println(e.getMessage());
e.printStackTrace();
}
Serialização
n
Passo 3: carregar o objeto usando
ObjectInputStream:
Dados dadol;
try{
FileInputStream is = new FileInputStream(“teste");
ObjectInputStream iarq = new ObjectInputStream(is);
dadol = (Dados) iarq.readObject();
iarq.close();
}catch(IOException e){
System.out.println(e.getMessage());
e.printStackTrace();
}
dadol.imp();
‹# ›
Roteiro
n
Introdução a Arquivos
n
Streams
n
Serialização
n
Arquivos de Acesso Randômico
n
Exercícios
Arquivos de Acesso Randômico
n
Arquivos de acesso randômico (ou aleatório)
podem ser criados com auxílio da classe
RandomAccessFile
n
Arquivo de acesso randômico
Permite ler a partir de qualquer posição no
arquivo
n Acesso rápido
n
Arquivos de Acesso Randômico
n
A classe RandomAccessFile permite não apenas
acesso direto a posições específicas do arquivo
(em bytes), como também permite que se trabalhe
n o s m o d o s “le itu ra ” (r), “g ra va çã o ” (w ) o u “le itu ra e
g ra va çã o ” (rw )
n
A classe RandomAccessFile possui métodos
semelhantes a DataInputStream e
DataOutputStream
n
Podem ser inseridos novos dados sem destruir os
dados previamente gravados
‹# ›
Arquivos de Acesso Randômico
n
Implementados usando registros de tamanho
fixo
n
Como um trem com vários vagões
n
Facilita o cálculo da localização exata de qualquer
registro em relação ao início do arquivo
n
0
Alguns cheios e outros vazios
1
0
0
2
0
0
3
0
0
4
0
0
5
0
0
}
b
y
teo
ffsets
}
}
}
}
}
}
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
b
y
tes
b
y
tes
b
y
tes
b
y
tes
b
y
tes
b
y
tes
Aqui,os registros
possuem 100 bytes cada
(um não irá jamais
sobrescrever o outro).
Arquivos de Acesso Randômico
n
Classe RandomAccessFile
n
Faz o mesmo que DataInputStream e
DataOutputStream
n
n
Pode ler/escrever dados binários
Ao associar RandomAccessFile a um arquivo
Dados são lidos/escritos na localização do arquivo
especificada pelo ponteiro de posição no arquivo (ou
file pointer)
n Todos os dados são tratados como tipos primitivos
n
n
Tem tamanho fixo (double é 8 bytes, int é 4, etc.)
Arquivos de Acesso Randômico
n
Para posicionar o ponteiro de posição sobre
um ponto específico do arquivo utilize o
método seek.
n
Exemplo:
n
Método que lê diretamente um double
armazenado após 2 int.
‹# ›
Arquivos de Acesso Randômico
public void leDoubleApos2Ints(){
try{
RandomAccessFile rf = new
RandomAccessFile("dados.dat","r");
rf.seek(4*2);
System.out.println("Valor do Double: "+rf.readDouble());
rf.close();
}
catch(IOException e){
System.out.println(e.getMessage()); }
}
Arquivos de Acesso Randômico
n
Para acrescentar dados em um arquivo
basta abri-lo para leitura e gravação e
posicionar o ponteiro de posição no fim do
arquivo.
n
Exemplo:
Arquivos de Acesso Randômico
public void acrescentaInt(int i){
try{
RandomAccessFile rf = new
RandomAccessFile("dados.dat","rw");
rf.seek(rf.length());
rf.writeInt(i);
rf.close();
} catch(IOException e){
System.out.println(e.getMessage());
}
}
‹# ›
Arquivos de Acesso Randômico
Para ler dados de um arquivo de tamanho
desconhecido, trate EOFException.
n Exemplo:
n
public void leArq(){
FileInputStream is = null;
DataInputStream dis = null;
int aux;
leDados();
(continua...)
Arquivos de Acesso Randômico
try{
is = new FileInputStream("dados.dat");
dis = new DataInputStream(is);
while(true){
aux = dis.readInt();
System.out.println(aux);
}
}
catch (EOFException e){ }
catch (IOException e){
System.out.println(e.getMessage()); }
try {dis.close(); }
catch (IOException e){
System.out.println(e.getMessage()); }
}
Roteiro
n
Introdução a Arquivos
n
Streams
n
Serialização
n
Arquivos de Acesso Randômico
n
Exercícios
‹# ›
Exercícios
1) Implemente um método em JAVA que recebe um
ArrayList do tipo Ponto como parâmetro e
armazena os pontos em um arquivo chamado
pontos.dat. Em primeiro lugar deve ser
armazenada a quantidade de pontos e, na
seqüência, a lista de pontos (primeiro todas as
ordenadas, depois todas as abscissas).
2) Implemente um método em JAVA que seja
capaz de ler um arquivo criado pelo método do
exercício 2. O método deve devolver um
ArrayList do tipo Ponto com os pontos lidos.
Exercícios
3) Faça um método JAVA que recebe uma string
com o nome de um arquivo e uma lista
encadeada por parâmetro. Este método deverá
gravar a lista em um arquivo binário.
4) Faça um método JAVA que recebe uma string
com o nome de um arquivo e uma lista
encadeada por parâmetro. Este método deverá
ler a lista do arquivo cujo nome é passado por
parâmetro.
‹# ›
Download