Arquivos de Dados - PUC-SP

Propaganda
Pontifícia Universidade Católica de São Paulo
Departamento de Ciência da Computação
Apontamento 16
Maio de 2004
LP: Laboratório de Programação
Prof. ISVega
Arquivos Binários
CONTEÚDO
16.1 Processamento de Arquivos de Dados . . . . .
16.2 Processamento de Bytestreams . . . . . . . .
16.2.1Escrita COM Filtros . . . . . . . . . . .
16.3 Aplicação: Controle de Estoque . . . . . . . .
16.3.1Criação do Arquivo de Estoque . . . . .
16.3.2Processamento do Arquivo de Estoque
Exercícios . . . . . . . . . . . . . . . . . . . . . . . .
16.4 Anexo: Listagem do Protótipo . . . . . . . . .
16.4.1Pacote Principal . . . . . . . . . . . . .
16.4.2Pacote dados . . . . . . . . . . . . . . .
16.4.3Pacote estoque2 . . . . . . . . . . . . .
Objetivos
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
2
2
6
6
8
12
14
14
14
15
• Mostrar como ler e escrever arquivos binários em
Java.
16.1 Processamento de Arquivos de Dados
Informações são armazenadas em um arquivo ou na forma de bytes (dados) ou na
forma de texto (linhas de caracteres). Assim, as seqüências de bytes podem ser
1
Laboratório de Programação
Maio de 2004
vistas como texto ou como dados (estruturados). No primeiro caso, deve-se utilizar
instâncias do tipo Reader e Writer. No segundo caso, deve-se usar instâncias do
tipo FilterInputStream e FilterOutputStream.
16.2 Processamento de Bytestreams
Processamento de Dados COM Filtros
O processamento de arquivos de dados (binários) com filtros (precisa indicar um
FileInputStream ou FileOutputStream como origem do texto) é feito por instâncias da classe DataInputStream e DataOutputStream.
16.2.1 Escrita COM Filtros
A escrita de dados sem filtros é feita por instâncias da classe DataOutputStream,
segundo o padrão:
hlab/padrao/EscritaDadosFiltro.javai≡
hEscrita dados: dependênciasi
public class EscritaDadosFiltro {
public escrever() {
hEscrita dados: criar arquivo de dadosi
hEscrita dados: escrever dadosi
hEscrita dados: fechar arquivo de dadosi
}
}
Dependências Externas O método de escrita em arquivos de dados depende das
seguintes classes da biblioteca Java:
hEscrita dados: dependênciasi≡
import java.io.FileOutputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
Método de Escrita
O primeiro passo envolve a criação do arquivo e do filtro de escrita de dados:
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-2
Laboratório de Programação
Maio de 2004
hEscrita dados: criar arquivo de dadosi≡
// ABERTURA
DataOutputStream filtro = null;
try {
FileOutputStream arquivo = new FileOutputStream( "dados.dat" );
filtro = new DataOutputStream( arquivo );
}
catch( FileNotFoundException e ) {
System.out.println( "Falha na criação do arquivo" );
}
Em seguida, escrevem-se os dados em si:
hEscrita dados: escrever dadosi≡
// ESCRITA
try {
filtro.writeChar( ’a’ );
}
catch( IOException e ) {
System.out.println( "Falha na escrita" );
}
Por último, fecha-se o arquivo de dados:
hEscrita dados: fechar arquivo de dadosi≡
// FECHAMENTO
try {
filtro.close();
}
catch( IOException e ) {
System.out.println( "Falha ao fechar" );
}
Serviços de Escrita
Os serviços oferecidos pelo filtro de escrita são:
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-3
Laboratório de Programação
Maio de 2004
flush
close
size
write (byte)
writeBoolean
writeByte
writeBytes
writeChar
writeChars (unicode strings)
writeDouble
writeFloat
writeInt
writeLong
writeShort
writeUTF
Leitura COM Filtros
A leitura de dados com filtros é feita por instâncias da classe
DataInputStream.
hlab/padrao/LeituraDadosFiltro.javai≡
hLeitura dados: dependênciasi
public class LeituraDadosFiltro {
public ler() {
hLeitura dados: abrir e criar o filtroi
hLeitura dados: ler os dadosi
hLeitura dados: fechar o arquivoi
}
}
Dependências Externas O método de escrita em arquivos de dados depende das
seguintes classes da biblioteca Java:
hLeitura dados: dependênciasi≡
import java.io.FileInputStream;
import java.io.DataInputStream;
import java.io.FileNotFoundException;
import java.io.EOFException;
import java.io.IOException;
Método de Leitura
O primeiro passo envolve a abertura do arquivo a ser lido e do filtro de leitura de
dados:
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-4
Laboratório de Programação
Maio de 2004
hLeitura dados: abrir e criar o filtroi≡
// ABERTURA
DataInputStream filtro = null;
try {
FileInputStream arquivo = new FileInputStream( "dados.dat" );
filtro = new DataInputStream( arquivo );
}
catch( FileNotFoundException e ) {
System.out.println( "Arquivo inexistente" );
}
Em seguida, lêem-se os dados em si:
hLeitura dados: ler os dadosi≡
// LEITURA
try {
System.out.println( filtro.readChar() );
}
catch( EOFException e ) {
System.out.println( "Fim do arquivo" );
}
catch( IOException e ) {
System.out.println( "Falha na leitura" );
}
Por último, fecha-se o arquivo de dados:
hLeitura dados: fechar o arquivoi≡
// FECHAMENTO
try {
filtro.close();
}
catch( IOException e ) {
System.out.println( "Falha ao fechar");
}
Serviços de Leitura
Os serviços oferecidos pelo filtro de leitura são:
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-5
Laboratório de Programação
Maio de 2004
close
read (byte)
readBoolean
readByte
readChar
readDouble
readFloat
readFully
readInt
readLong
readShort
readUnsignedByte
readUnsignedShort
readUTF (strings)
skipBytes
16.3 Aplicação: Controle de Estoque
Esta seção cria um arquivo contendo produtos, quantidades e preços unitários, o
qual é posteriormente processado, produzindo um relatório de estoque. O arquivo,
nesta aplicação, é do tipo arquivo de dados.
16.3.1 Criação do Arquivo de Estoque
A criação do arquivo de estoque, denominado estoque.dat, segue o padrão anteriormente descrito para o caso de escrita arquivos de dados.
hlab/estoque2/Estoquista.javai≡
hpacotes importados na criação do estoquei
public class Estoquista {
DataOutputStream filtro = null;
public void cadastrar() {
habrir o arquivo de dados e criar o filtro de escrita do estoquei
hobter as quantidades de produtos e escrever no arquivoi
hesvaziar o filtro e fechar o arquivo de dadosi
System.exit(0);
}
}
Dependências Externas
As seguintes classes são necessárias para criar o arquivo de estoque de produtos:
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-6
Laboratório de Programação
Maio de 2004
hpacotes importados na criação do estoquei≡
import java.io.FileOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
Método de Criação do Estoque
A abertura e criação do filtro de escrita obedece ao padrão:
habrir o arquivo de dados e criar o filtro de escrita do estoquei≡
// ABRIR ARQUIVO DE DADOS E CRIAR FILTRO
try {
FileOutputStream arqDados = new FileOutputStream( "estoque.dat" );
filtro = new DataOutputStream( arqDados );
}
catch( IOException e ) {
System.out.println( e );
System.exit( 1 );
}
A parte principal da criação do arquivo de estoque deve percorrer cada produto e
solicitar que o estoquista informe a quantidade atual existente. Inicialmente os
produtos e preços unitários são definidos. Em seguida, cria-se um leitor optico
para a leitura das quantidades. Uma repetição controlada por contador percorre
cada produto e solicita a quantidade existente. Este valor é convertido para int e
posteriormente escrito no arquivo de dados. Um aspecto importante nesta parte do
método de escrita é que a quantidade de caracteres que compõe o nome do produto
precede este nome no arquivo:
hobter as quantidades de produtos e escrever no arquivoi≡
// ESCREVER NO ARQUIVO DE DADOS
try {
String[] produtos = { "Lapis", "Borracha", "Caderno", "Caneta" };
double[] precos = { 0.70, 0.35, 5.00, 1.20 };
LeitorOptico optico = new LeitorOptico();
for( int i = 0; i < produtos.length; i++ ) {
int qtde =
optico.obterInt( "Quantidade de " + produtos[i] + "?");
filtro.writeInt( produtos[i].length() ); // <- tamanho do string
filtro.writeChars( produtos[i] );
filtro.writeInt( qtde );
filtro.writeDouble( precos[i] );
}
optico = null;
}
catch( IOException e ) {
System.out.println( e );
System.exit( 1 );
}
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-7
Laboratório de Programação
Maio de 2004
A parte final esvazia o filtro e fecha o arquivo de dados contendo as informações
sobre o estoque atual:
hesvaziar o filtro e fechar o arquivo de dadosi≡
// ESVAZIAR FILTRO E FECHAR O ARQUIVO DE DADOS
try {
filtro.flush();
filtro.close();
}
catch( IOException e ) {
System.out.println( e );
System.exit( 1 );
}
O contexto envolvendo o leitor óptico apenas solicita a quantidade de produto disponível no estoque, simulando o dispositivo real de leitura utilizado pelo estoquista:
hlab/estoque2/LeitorOptico.javai≡
import javax.swing.JOptionPane;
public class LeitorOptico {
public int obterInt( String pergunta ) {
String linha = JOptionPane.showInputDialog( pergunta );
int n = 0;
try {
n = Integer.parseInt( linha );
}
catch( NumberFormatException e ) {
System.out.println( "Quantidade desconhecida" );
}
return n;
}
}
16.3.2 Processamento do Arquivo de Estoque
O processamento do arquivo de estoque deve ler os valores informados e gerar um
relatório da situação atual dos produtos.
hlab/estoque2/Estoque.javai≡
hpacotes importados no processamento do estoquei
public class Estoque {
DataInputStream filtro = null;
public void recuperarItens() {
habrir o arquivo de dados e criar o filtro de leitura do estoquei
hcarregar as informações sobre cada produto e gerar o relatórioi
hfechar o arquivo de estoquei
}
hmostrar o relatório do estoquei
}
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-8
Laboratório de Programação
Maio de 2004
São os seguintes os arquivos importados para o processamento do estoque:
hpacotes importados no processamento do estoquei≡
import java.io.FileInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.EOFException;
A abertura do arquivo de estoque para leitura, segue o padrão normal visto anteriormente:
habrir o arquivo de dados e criar o filtro de leitura do estoquei≡
// ABRIR ARQUIVO DE DADOS E CRIAR FILTRO
try {
FileInputStream arqDados = new FileInputStream( "estoque.dat" );
filtro = new DataInputStream( arqDados );
}
catch( FileNotFoundException e ) {
System.out.println( e );
System.exit( 1 );
}
A carga de informações do arquivo faz uso do filtro de leitura de dados. O nome do
produto, sua quantidade e o preço unitário são carregados diretamente do arquivo.
A partir deles, um novo contexto da classe Item é construído, sendo de imediato
inserido na lista produtos, representando o estoque atual:
hcarregar as informações sobre cada produto e gerar o relatórioi≡
// LER DO ARQUIVO DE DADOS
Item[] produtos = new Item[ 100 ];
int n = 0;
try {
hcarregar todos os itens do arquivoi
}
catch( IOException e ) {
System.out.println( e );
System.exit( 1 );
}
A carga de todos os itens do arquivos é feita com uma estrutura de controle de
repetição com parada por sentinela:
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-9
Laboratório de Programação
Maio de 2004
hcarregar todos os itens do arquivoi≡
boolean acabou = false;
while( ! acabou ) {
try {
hcarregar um item do arquivo de estoquei
n++;
}
catch( NumberFormatException e ) {
System.out.println(
"ERRO no arquivo de entrada: dados ignorados" );
}
catch( EOFException e ) {
acabou = true;
}
}
A carga individual de um item recupera cada uma das suas partes:
hcarregar um item do arquivo de estoquei≡
String produto = "";
int k = filtro.readInt(); // <- tamanho do nome do produto
for( int i = 0; i < k; i++ ) {
produto += filtro.readChar();
}
int qtde = filtro.readInt();
double preco = filtro.readDouble();
produtos[n] = new Item( produto, qtde, preco );
Após a leitura de todos os dados do arquivo de estoque, ele é fechado:
hfechar o arquivo de estoquei≡
// FECHAR O ARQUIVO DE DADOS
try {
filtro.close();
}
catch( IOException e ) {
System.out.println( e );
System.exit( 1 );
}
Por último, a lista de produtos é apresentada, contabilizando-se o valor total de cada
produto disponível:
hmostrar o relatório do estoquei≡
public void gerarRelatorio() {
for( int i = 0; i < produtos.length; i++ ) {
System.out.println( produtos[i] );
}
}
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-10
Laboratório de Programação
Maio de 2004
A classe Item modela a estrutura de informações de um item estocado. A estrutura
é composta pelo nome do produto, sua quantidade em estoque e o seu preço unitário. Adicionalmente, uma propriedade de formatação é utilizada no momento da
conversão feita pelo serviço toString():
hlab/estoque2/Item.javai≡
import java.text.DecimalFormat;
public class Item {
private String _produto;
private int _quantidade;
private double _preco;
private DecimalFormat _formato;
public Item( String produto, int quantidade, double preco ) {
_produto = produto;
_quantidade = quantidade;
_preco = preco;
_formato = new DecimalFormat( "0.##" );
}
public String toString() {
return _produto + ":" + _quantidade + " a " + _preco + " = " +
_formato.format( (_quantidade * _preco) );
}
}
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-11
Laboratório de Programação
Maio de 2004
E XERCÍCIOS
16.1 P ROCESSO
DE E SCRITA DE D ADOS
Implemente e execute o programa de
escrita em arquivos de dados com filtro (EscritaDadosFiltro.java na seção de
listagens).
Tarefa 16.1.1
Crie o projeto ex16.1.
Tarefa 16.1.2
Implemente de acordo com o texto.
16.2 P ROCESSO
L EITURA DE D ADOS
Implemente e execute o programa de
escrita em arquivos de dados com filtro (LeituraDadosFiltro.java na seção de
listagens).
DE
Tarefa 16.2.1
Crie o projeto ex16.2.
Tarefa 16.2.2
Implemente de acordo com o texto.
16.3 C ONTROLE
DE
E STOQUE
Sobre o sistema de controle de estoque:
Tarefa 16.3.1
Crie o projeto ex16.3.
Tarefa 16.3.2
Implemente o programa do sistema de controle de estoque.
Tarefa 16.3.3
Crie os objetos aldo:Estoquista e bazar:Estoque.
Tarefa 16.3.4
Qual o efeito do processamento da mensagem aldo.cadastrar()?
Tarefa
16.3.5
Qual
o
efeito
do
processamento
das
bazar.recuperarItens() seguida de bazar.gerarRelatorio()?
mensagens
Tarefa 16.3.6 Altere o arquivo Estoque.java de modo a ser apresentado o valor
total estocado (somatória dos valores dos produtos estocados).
OBS: procure utilizar um novo método totalizar(produtos):void que recebe o
array produtos por referência e retorna o cálculo solicitado.
16.4 C ÁLCULO
M ÉDIA
Crie uma aplicação que calcula o mostra as notas e
médias finais de uma turma de alunos.
Tarefa 16.4.1
DE
Crie o projeto ex16.4.
Tarefa 16.4.2 Crie a classe Aluno.java descrevendo um aluno com as seguintes
informações: primeiro nome, número de inscrição, notas das provas P1, P2 e PS.
Por exemplo:
Carlos 112233 5.5 7.8 Andrea 333222 4.6 2.3 8.8
Zizi
545454 3.8 7.7 (Estas informações devem estar armazenadas no arquivo de dados alunos.txt)
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-12
Laboratório de Programação
Maio de 2004
Tarefa 16.4.3 Crie a classe Turma.java, que lê o arquivo alunos.txt e mostra
todas as suas linhas na tela.
Tarefa 16.4.4 Acrescente um método na classe Turma.java, de modo que ele
armazene o conteúdo do arquivo alunos.txt em um arquivo de dados denominado
alunos.dat. Quais os tamanhos destes arquivos?
Tarefa 16.4.5 Acrescente a classe Disciplina.java, de forma que seja carregado
o arquivo de dados alunos.dat e sejam apresentadas todas as informações sobre
um aluno, inclusive a média final de cada um deles. A média final é calculada da
seguinte forma:
mf =
P1 + 2 × P2
2
caso o aluno não tenha feito PS .
Se o aluno fez PS , esta nota deverá substituir a menor das notas P 1 ou P 2:
mf =
PS + 2 × P 2
2
mf =
P 1 + 2 × PS
2
se P 1 < P 2; ou
se P 2 < P 1.
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-13
Laboratório de Programação
Maio de 2004
16.4 Anexo: Listagem do Protótipo
16.4.1 Pacote Principal
16.4.2 Pacote dados
Classe EscritaDadosFiltro.java
import java.io.FileOutputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class EscritaDadosFiltro {
public static void main( String[] args ) {
// ABERTURA
DataOutputStream filtro = null;
try {
FileOutputStream arquivo = new FileOutputStream( "dados.dat" );
filtro = new DataOutputStream( arquivo );
}
catch( FileNotFoundException e ) {
System.out.println( "Inexistente" );
}
// ESCRITA
try {
filtro.writeChar( ’a’ );
}
catch( IOException e ) {
System.out.println( "Falha na escrita" );
}
// FECHAMENTO
try {
filtro.close();
}
catch( IOException e ) {
System.out.println( "Falha ao fechar" );
}
}
}
Classe LeituraDadosFiltro.java
import java.io.FileInputStream;
import java.io.DataInputStream;
import java.io.FileNotFoundException;
import java.io.EOFException;
import java.io.IOException;
public class LeituraDadosFiltro {
public static void main( String[] args ) {
// ABERTURA
DataInputStream filtro = null;
try {
FileInputStream arquivo = new FileInputStream( "dados.dat" );
filtro = new DataInputStream( arquivo );
}
catch( FileNotFoundException e ) {
System.out.println( "Inexistente" );
}
// LEITURA
try {
System.out.println( filtro.readChar() );
}
catch( EOFException e ) {
System.out.println( "Fim do arquivo" );
}
catch( IOException e ) {
System.out.println( "Falha na leitura" );
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-14
Laboratório de Programação
Maio de 2004
}
// FECHAMENTO
try {
filtro.close();
}
catch( IOException e ) {
System.out.println( "Falha ao fechar");
}
}
}
16.4.3 Pacote estoque2
Classe Estoque.java
import java.io.FileInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.EOFException;
public class Estoque {
DataInputStream filtro = null;
public void recuperarItens() {
// ABRIR ARQUIVO DE DADOS E CRIAR FILTRO
try {
FileInputStream arqDados = new FileInputStream( "estoque.dat" );
filtro = new DataInputStream( arqDados );
}
catch( FileNotFoundException e ) {
System.out.println( e );
System.exit( 1 );
}
// LER DO ARQUIVO DE DADOS
Item[] produtos = new Item[ 100 ];
int n = 0;
try {
boolean acabou = false;
while( ! acabou ) {
try {
String produto = "";
int k = filtro.readInt(); // <-- tamanho do nome do produto
for( int i = 0; i < k; i++ ) {
produto += filtro.readChar();
}
int qtde = filtro.readInt();
double preco = filtro.readDouble();
produtos[n] = new Item( produto, qtde, preco );
n++;
}
catch( NumberFormatException e ) {
System.out.println( "ERRO no arquivo de entrada: dados ignorados" );
}
catch( EOFException e ) {
acabou = true;
}
}
}
catch( IOException e ) {
System.out.println( e );
System.exit( 1 );
}
// FECHAR O ARQUIVO DE DADOS
try {
filtro.close();
}
catch( IOException e ) {
System.out.println( e );
System.exit( 1 );
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-15
Laboratório de Programação
Maio de 2004
}
}
public void gerarRelatorio() {
for( int i = 0; i < produtos.length; i++ ) {
System.out.println( produtos[i] );
}
}
}
Classe Estoquista.java
import java.io.FileOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class Estoquista {
DataOutputStream filtro = null;
public void cadastrar() {
// ABRIR ARQUIVO DE DADOS E CRIAR FILTRO
try {
FileOutputStream arqDados = new FileOutputStream( "estoque.dat" );
filtro = new DataOutputStream( arqDados );
}
catch( IOException e ) {
System.out.println( e );
System.exit( 1 );
}
// ESCREVER NO ARQUIVO DE DADOS
try {
String[] produtos = { "Lapis", "Borracha", "Caderno", "Caneta" };
double[] precos = { 0.70, 0.35, 5.00, 1.20 };
LeitorOptico optico = new LeitorOptico();
for( int i = 0; i < produtos.length; i++ ) {
int qtde =
optico.obterInt( "Quantidade de " + produtos[i] + "?");
filtro.writeInt( produtos[i].length() ); // <-- tamanho do string
filtro.writeChars( produtos[i] );
filtro.writeInt( qtde );
filtro.writeDouble( precos[i] );
}
optico = null;
}
catch( IOException e ) {
System.out.println( e );
System.exit( 1 );
}
// ESVAZIAR FILTRO E FECHAR O ARQUIVO DE DADOS
try {
filtro.flush();
filtro.close();
}
catch( IOException e ) {
System.out.println( e );
System.exit( 1 );
}
System.exit(0);
}
}
Classe Item.java
import java.text.DecimalFormat;
public class Item {
private String _produto;
private int _quantidade;
private double _preco;
private DecimalFormat _formato;
public Item( String produto, int quantidade, double preco ) {
_produto = produto;
_quantidade = quantidade;
_preco = preco;
_formato = new DecimalFormat( "0.##" );
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-16
Laboratório de Programação
Maio de 2004
}
public String toString() {
return _produto + ":" + _quantidade + " a " + _preco + " = " +
_formato.format( (_quantidade * _preco) );
}
}
@%%% FIGURA --%\figuraDirPP[0.6]{\rota/\diretorio/images}
%{\dirFig-f-12}
%{Esquema de um tanque de água.}
%%% --- FIGURA
%\begin{isvSSlide}
%\isvExercitar{5}
%%\isvDiscutir{1}
%\end{isvSSlide}
Classe LeitorOptico.java
import javax.swing.JOptionPane;
public class LeitorOptico {
public int obterInt( String pergunta ) {
String linha = JOptionPane.showInputDialog( pergunta );
int n = 0;
try {
n = Integer.parseInt( linha );
}
catch( NumberFormatException e ) {
System.out.println( "Quantidade desconhecida" );
}
return n;
}
}
c
Copyright °1998-2004,
Dr. Italo S. Vega
16-17
Download