streams profa. patrícia a. jaques [email protected] unisinos

46
Streams Profa. Patrícia A. Jaques [email protected] Unisinos

Upload: internet

Post on 22-Apr-2015

112 views

Category:

Documents


4 download

TRANSCRIPT

Page 1: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Streams

Profa. Patrícia A. [email protected]

Unisinos

Page 2: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Lendo do Console com a classe Scanner

import java.util.Scanner;

public class TestaScanner {

public static void main(String args[]) {

Scanner scanner = new Scanner(System.in);

System.out.println("Digite um numero:");

String numero = scanner.nextLine();

System.out.println("O numero digitado foi:" + numero);

}

}Laboratório 2 - Patrícia Jaques 2

Page 3: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 3

Entrada e saída de dados em Java

• A maioria dos programas precisa acessar e enviar dados externos ao programa.

• Os dados de entrada podem ser provenientes de um arquivo em disco, de um teclado ou de uma conexão em rede.

• Java permite lidar com todos os tipos de entrada e saída através de uma abstração conhecida como stream.

arquivo Uma stream

Programa

Page 4: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Manipulação de Dados em um Computador

• Armazenamento em array é temporário– dados são perdidos quando programa finaliza a execução

• Armazenar dados em memória secundária (persistente)– editor de texto

• Computador processa informação como 0 e 1– bit menor unidade do computador

– manipulado por circuitos

• Programador: – incômodo programar em bits

– trabalham com conjunto de caracteres do computador: letras, números e símbolos especiais

• Conjunto de caracteres:– como computador só trabalha com 0 e 1, cada caractere é representado por

um padrão de 0 e 1

– Byte: 8 bits

• Formatos para caracteres:– ASCII (American Standard Code for Information Interchange): caracteres

representados por 1 byte

– UNICODE: caracteres representados por 2 bytes

Laboratório 2 - Patrícia Jaques 4

Page 5: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Tabela ASCII

Laboratório 2 - Patrícia Jaques 5

Page 6: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Arquivo

• Na visão do sistema operacional, um arquivo é conjunto de bytes.

• A organização dos bytes em um arquivo é uma visão criada pelo aplicativo.– arquivo ppt– arquivo ASCII– conjunto de registros em um arquivo de banco de dados

• Java vê arquivo como um fluxo seqüencial de bytes – Cada arquivo acaba com um marcador de fim: que Java

avisa ao programador através de exceção ou do valor devolvido pelo método que processa (lê) o arquivo.

• Trabalhando com arquivos em Java:– Abrir o arquivo– Processar o arquivo (ler seus bytes até o final do arquivo)

ou escrever no arquivo– Fechar o arquivo

Laboratório 2 - Patrícia Jaques 6

Page 7: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 7

Uma stream

Programa

01001010101010101001010010101010010101010101010101

J

bytes ou caracteres

Streams de Leitura

Programa

01001010101010101001010010101010010101010101010101

bytes ou caracteres

J

Streams de Escrita

Page 8: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 8

Streams são unidirecionais

• O pacote java.io define um grande número de classes para ler e escrever streams. – import java.io.*;

• Streams são unidirecionais– Streams para leitura– Stream para escrita

• Streams permitem:– acesso seqüencial dos dados do arquivo:

• programa lê os dados a partir do início do arquivo • lê todos os dados consecutivamente até encontrar dado procurado

ou chegar no final do arquivo• Não permite voltar ao início do arquivo para lê-lo novamente:

necessário fechar e reabrir o arquivo.– acesso aleatório dos dados do arquivo:

• permite reposicionar ponteiro do arquivo (o número que indica a posição do próximo byte do arquivo a ser lido ou gravado) para voltar ao início do arquivo ou diretamente a uma outra posição.

Page 9: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 9

Lendo Bytes e Caracteres

• As classes InputStream e OutputStream, bem como as suas subclasses, são usadas para ler e escrever stream de bytes;

• As classes Reader e Writer (e subclasses) são usadas para ler e escrever streams de caracteres (2 bytes).

Bytes

Caracteres

InputStream – LerOutputStream - Escrever

Reader – LerWriter - Escrever

Classes abstratas

Classes abstratas

Quando usar: para ler e escrever dados binários, tais como imagens e sons

Quando usar: para ler e escrever dados binários, tais como imagens e sons

Quando usar: para ler e escrever dados textuais

Quando usar: para ler e escrever dados textuais

Page 10: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 10

Obtendo as propriedades de um arquivo – class File

import java.io.File;

import java.util.Date;

import java.text.*;

class TestaArquivo {

public static void main (String args []) {

File f = new File ("C:/Documents and Settings/Patricia Jaques/Mes documents/Cursos/CursoJava/ExerciciosApostila/03_Poo/Circle.java");

System.out.println ("Nome do arquivo: "+f.getName ());

System.out.println ("Caminho: "+f.getPath ()); // retorna diretório denotado pelo nome

System.out.println ("Caminho Absoluto: "+f.getAbsolutePath ()); // consulta SO

System.out.println ("Diretório pai: "+f.getParent ());

System.out.println (f.exists() ? "existe":"não existe");

System.out.println (f.canWrite() ? "pode ser gravado":"não pode ser gravado");

System.out.println (f.canRead() ? "pode ser lido":"não pode ser lido");

System.out.println (f.isDirectory () ? "é diretório":"não é diretório");

DateFormat df = new SimpleDateFormat ("dd/MM/yyyy");

Date data = new Date (f.lastModified ());

System.out.println ("Ultima modificação do arquivo: "+df.format (data));

System.out.println ("Tamanho do arquivo: "+f.length ()+ " bytes.");

}

} // da class TestaArquivo

Page 11: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 11

Listando diretórios

import java.io.File;

class ListaDir {

public static void main (String args [ ]) {

String nomeDir = ".";

File f1 = new File (nomeDir);

if (f1.isDirectory ( ))

{

System.out.println ("Diretório "+nomeDir);

String s[ ] = f1.list( );

for (int i=0; i<s.length; i++)

{

File f = new File (s[i]);

System.out.print (s[i]);

if (f.isDirectory ( )) System.out.println (" <dir> ");

else System.out.println (" <file>");

}

}

else System.out.println (nomeDir + " não é um diretório.");

}

} // da class

Page 12: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Trabalhando com Arquivo Texto

Page 13: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 13

Lendo e escrevendo texto

• A plataforma armazena caracteres segundo convenção Unicode. As classes filhas das classes Reader e Writer convertem os caracteres Unicode de e para o formato de caractere usado pela plataforma (geralmente ASCII-8).

Page 14: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 14

Hierarquia de Classes de Reader e Writer

Leit

ura

Esc

rita

PrintWriter

Page 15: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 15

Trabalhando com caracteres – Reader e Writer

• Reader• int read() • int read(char cbuf[]) • int read(char cbuf[], int offset, int length)

• Writer• void write(int c) • void write(char cbuf[]) • void write(char cbuf[], int offset, int length)

• void write(String str)• void write(String str, int off, int len)n

ovas

Page 16: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 16

FileReader e FileWriter

• FileReader:– Para ler arquivos textos– FileReader (File file)– FileReader (String fileName)

• FileWriter– Para escrever em arquivos textos– FileWriter (File file)– FileWriter (File file, boolean append)– FileWriter (String fileName) – FileWriter (String fileName, boolean append)

Page 17: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 17

Lendo Arquivos Textos

• Caracteres são armazenados em buffers após serem lidos.

• BufferedReader– FileReader fr = new FileReader (filename);– BufferedReader in = new BufferedReader (fr);

– Método “String readLine()”: Retorna a próxima linha de texto do arquivo;

Page 18: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 19

Lendo linhas de um arquivo texto

import java.io.*;

public class LeArquivo {public static void main(String args[]) {

String filename = "E:\\aulas\\lab2\\t1.txt";try {

FileReader fr = new FileReader(filename);BufferedReader in = new BufferedReader(fr);String line = in.readLine(); while (line != null) {

System.out.println(line);line = in.readLine();

}in.close();

} catch (FileNotFoundException e) {System.out.println("Arquivo \""+filename+"\" não

existe.");} catch (IOException e) {

System.out.println("Erro na leitura do arquivo " + filename+".");

}}

}

Page 19: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 20

Método Split

class BuscaPalavrasEmUmaString {

public static void main (String args[ ]) {

String texto = "Isto#é#um#texto#de#teste";

// usando delimitador #

String result[] = texto.split("#");

for (int i=0; i<result.length; i++) {

System.out.println (i+1+": "+result[i]);

}

} // main

} // class

c:\> java BuscaPalavrasEmUmaString1: Isto2: é3: um4: texto5: de6: teste

Page 20: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 21

Exercício 2 – Separando Tokens

• Crie uma classe chamada Book• Esta classe vai ter os seguintes atributos:

– String title; – String isbn; – String publisherId; – String url; – float price;

• Leia o arquivo Books.txt e guarde os dados de cada linha dentro de um objeto Book. Para fazer isso:

– Leia uma linha por vez com o método readLine( ) da classe BuffererReader• Line = in.readLine();

– Cada linha da tabela é uma linha do arquivo.– Cada coluna do arquivo é uma string da linha separa pelo delimitador ‘|’ (pipe).

• Para obter esta string use o método split da classe String. Ex:• String result [ ] = line.split(“\\|”);

– Cada token do split() vai ser um dado do objeto Book, de acordo com a sua ordem. O primeiro token vai ser sempre o title e assim por diante:

• String title = result[0];• String isbn = result[1];• ….• Book b = new Book();• b.setTitle(title);• …

• Crie uma array de books (ou vector) para guardar todos os objetos e percorra essa array imprimindo o conteúdo de seus objetos

• Não esqueça de importar o pacote java.io.*;

Page 21: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 22

PrintWriter

• void println (String x) • void println (int x) …

• PrintWriter (OutputStream out)• PrintWriter (Writer out) // default=sem flush automático, nem para

método println• PrintWriter (Writer out, boolean autoFlush)

– autoflush == true dá flush com método println– só da flush com o método println e não com o caracter /n

• converte caractereres UNICODE Java para formato de caracter da plataforma onde o programa Java está executando    

méto

dos

con

stru

tore

s

Page 22: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 23

Escrevendo linhas em um arquivo texto

import java.io.*;class EscreveArquivo {

public static void main (String args [ ]) {try {

File f = new File ("MeuArquivo.txt");FileWriter fr = new FileWriter (f);PrintWriter out = new PrintWriter (fr);out.println ("Curso de Java: Arquivo gerado pelo

programa.");out.close();

}catch (IOException e) {

System.out.println ("Erro ao escrever arquivo.");}

}}

Page 23: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Exercício de Agenda de contatos

• O sistema de agenda deve manter uma lista de contatos. • Um contato padrão tem: nome, e-mail, telefone, endereço e

data do aniversário. Porém o contato pode ser enquadrado como de algum tipo específico: geral, cliente ou fornecedor. Para fornecedor, é interessante manter-se um índice de qualidade, pois pode ser necessário ter de escolher 1 entre vários fornecedores de um mesmo produto. Já para o cliente, deve-se atribuir uma data da última compra e uma classificação de fidelidade (ou valores possíveis são: fiel, freqüente, pouco freqüente e apenas uma vez). Por fim, da categoria geral, não é necessário guardar mais nenhum dado além dos do contato.

• O programa da agenda deve manter um menu de opções do programa: incluir contato (acrescenta numa lista de contatos ordenados por nome), excluir contato (retirar da lista), listar contatos, consulta dados de um contato e sair.

• OBS: – A inclusão de contatos deve acontecer na ordem alfabética pelo

campo nome.

Page 24: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Exercício de Agenda de contatos

• Ler e gravar de um arquivo registros de contatos de uma agenda de contatos. Formato do arquivo:– <id>;<tipo (0-geral, 1-cliente ou 2-fornecedor>;

<nome>;<telefone>;<email>;<endereço>;<nascimento>

– Para o tipo 1: <fidelidade>;<data ultima compra>– Para o tipo 2: <classificação>

• Colocar numa lista de contatos. Os contatos podem ser Geral, Cliente ou Fornecedor

• Colocar controle das seguintes exceções:– Arquivo não encontrado– Tipo de contato inválido (diferente de 0, 1 e 2)– Nome deve ter no mínimo duas partículas (nome e

sobrenome)– Problemas de conversão de String para os respectivos

tipos de dados. PARA ENTREGAR ATÉ O GA

Page 25: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Lendo e Escrevendo Dados Binários

Page 26: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Lendo Bytes e Caracteres

• As classes InputStream e OutputStream, bem como as suas subclasses, são usadas para ler e escrever stream de bytes;

• As classes Reader e Writer (e subclasses) são usadas para ler e escrever streams de caracteres (2 bytes).

Bytes

Caracteres

InputStream – LerOutputStream - Escrever

Reader – LerWriter - Escrever

Classes abstratas

Classes abstratas

Quando usar: para ler e escrever dados binários, tais como imagens e sons

Quando usar: para ler e escrever dados binários, tais como imagens e sons

Quando usar: para ler e escrever dados textuais

Quando usar: para ler e escrever dados textuais

Page 27: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Hierarquia de Classes de InpuStream e OutputStream

Serialização

Leit

ura

Esc

rita

Page 28: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

A Classe InputStream – abstract classPula

r para

posi

ção n

o t

exto

Page 29: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

A Classe OutputStream – abstract class

BufferedOutputStream

Page 30: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

FileInputStream e FileOutputStream

import java.io.*;public class CopiaArquivo { public static void main(String arg[]) throws IOException { FileInputStream in = new FileInputStream("CopiaArquivo.java"); // sobrescreve arquivo se ele já existe FileOutputStream out = new FileOutputStream (

"Copia de CopiaArquivo.java"); int c; while ((c = in.read()) != -1) out.write(c); in.close(); out.close(); }}

FileOutputStream (String name, boolean append) // escreve no final do arquivoFileOutputStream (File file) FileOutputStream (File file, boolean append)

Page 31: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Bufferização

• Assim como temos BufferedReader e BufferedWirter para bufferização de arquivos textos, quando estamos trabalhando com arquivos binários, podemos usar as classes:– BufferedInputStream– BufferedOutputStream

• Essas classes mantém os dados a serem escritos (no caso da BufferedOutputStream) ou lidos (BufferedOutputStream) em um buffer. Assim, o programa só vai realizar uma nova operação física de entrada ou saída de dados quando o buffer estiver vazio (no caso de leitura) ou cheio (no caso de saída).

• Em qualquer momento é possível forçar a saída (a gravação em arquivo) com o método flush( ) da classe BufferedOutputStream.

Page 32: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

import java.io.*;public class BufferInputOutput {

public static void main(String arg[]) { try { FileInputStream in = new FileInputStream("prim.txt"); BufferedInputStream bin = new BufferedInputStream(in); // sobrescreve arquivo se ele já existe FileOutputStream out = new FileOutputStream("Copia.txt"); BufferedOutputStream bout = new BufferedOutputStream(out); int c; while ((c = bin.read()) != -1) bout.write(c); bin.close(); bout.close(); } catch (IOException e) { e.printStackTrace(); }}

}

Page 33: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Exercícios

• Implemente o comando type do MS-DOS.• Voce deve fornecer ao seu programa a

seguinte linha de execução:– java Type nomeArquivo

• Ele mostrará na tela o conteúdo do arquivo• Antes de tentar abrir o arquivo, teste com a

classe File se o arquivo existe, e avise o usuário caso ele não exista

Page 34: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

PrintStream

• Ela grava em formato textual vários tipos de dados do java: boolean, char, int, etc

• Não gera exceção IOException• Dados são gravados (flush) automaticamente

a cada print• É o tipo da variável System.out.

Page 35: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

PrintStream

import java.io.*;

class PrintStreamDemo {  public static void main(String args[]){    try { FileOutputStream  out = new FileOutputStream("myfile.txt");          PrintStream ps = new PrintStream(out);            ps.println ("This data is written to a file:");        System.out.println ("Write successfully");        ps.close();   }   catch (Exception e){        System.out.println ("Error in writing to file");   }}

}

Page 36: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Arquivos de Acesso Randômico

Page 37: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Acesso Seqüencial x Acesso aleatório

• aceso seqüencial dos dados do arquivo:– programa lê os dados a partir do início do arquivo – lê todos os dados consecutivamente até encontrar

dado procurado ou chegar no final do arquivo– Não permite voltar ao início do arquivo para lê-lo

novamente: necessário fechar e reabrir o arquivo.– não é possível modificar um dado apenas do

arquivo. O arquivo deve ser totalmente sobrescrito.• acesso aleatório dos dados do arquivo:

– permite reposicionar ponteiro do arquivo (o número que indica a posição do próximo byte do arquivo a ser lido ou gravado) para voltar ao início do arquivo ou diretamente a uma outra posição.

– é possível modificar um dado apenas: interessante exigir que todos os registros tenham o mesmo tamanho

Laboratório 2 - Patrícia Jaques 36

Page 38: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Laboratório 2 - Patrícia Jaques 37

Arquivos de acesso randômico

import java.io.*;class ArquivoAcessoRandomico {

public static void main (String args []) throws java.io.IOException {RandomAccessFile raf = new RandomAccessFile ("Raf.txt",

"rw");raf.writeBytes ("Escrevendo a primeira linha.\n");raf.writeBytes ("Escrevendo a segunda linha.\n");raf.seek (0);String s = raf.readLine ();System.out.println ("Primeira linha no texto: "+s);raf.seek (raf.length()); // vai para o final do arquivoraf.writeBytes ("Escrevendo a última linha.\n");

}}// se arquivo já existe, substitui a partir da posição 0

Page 39: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

RandomAccessFile

• Métodos interessantes:– int read () - retorna byte lido como inteiro. Retorna -1

quando chegou no final do arquivo.– void write (int) – grava byte no arquivo– long length ( ) – retorna nro. de bytes no arquivo

Page 40: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

SerializaçãoLendo e Escrevendo objetos em arquivos

Page 41: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Armazenando objetos em arquivos

import java.io.*; class Serializacao {

public static void main (String args [ ]) {Pessoa p = new Pessoa ("Homem Aranha", 5, 8, 1937);File f = new File ("ArqSerializacao.arq");gravaObjeto (f, p);Pessoa p2 = (Pessoa) leObjeto (f);System.out.println ("Foi armazendo o objeto pessoa com os

valores:");System.out.println ("Nome: "+p2.getNome()+" \nData:

"+p2.getData());}

}

Page 42: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Armazenando objetos em arquivos

private static void gravaObjeto (File f, Object o) { try { FileOutputStream fos = new FileOutputStream (f); ObjectOutputStream os = new ObjectOutputStream (fos); os.writeObject (o); os.close (); } catch (IOException e) { System.out.println ("Erro ao gravar objeto."); }}

Page 43: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Armazenando objetos em arquivos

private static Object leObjeto (File f) { Object o = null;

try {FileInputStream fos = new FileInputStream (f);ObjectInputStream os = new ObjectInputStream (fos);o = os.readObject ();os.close ();

}catch (IOException e) {

System.out.println ("Erro ao abrir arquivo.");}catch (ClassNotFoundException ce) {

System.out.println ("Objeto não encontrado.");}return o;

} } // da class Serializacao

Page 44: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Armazenando objetos em arquivos

class Pessoa implements Serializable

{

String nome;

Data d;

public Pessoa (String nome, int dia, int mes, int ano)

{

this.nome = nome;

d = new Data (dia, mes, ano);

}

public String getNome ()

{

return nome;

}

public String getData ()

{

return d.getData ();

}

} // da class Pessoa

Page 45: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Armazenando objetos em arquivos

class Data implements Serializable

{

int dia;

int mes;

int ano;

public Data (int dia, int mes, int ano)

{

this.dia = dia;

this.mes = mes;

this.ano = ano;

}

public String getData ()

{

return dia+"/"+mes+"/"+ano;

}

} // da class Data

Page 46: Streams Profa. Patrícia A. Jaques pjaques@unisinos.br Unisinos

Exercícios

• Crie um programa que simule uma base de dados, armazenando registros de produtos em um arquivo.

• Um registro vai ser um objeto do tipo Book (que implementa a interface Serializable) que vimos no exercício anterior.

• O seu programa permite ler e armazenar os objetos Book que estão contidos no Vector e que foram lidos do arquivo Books.txt.

• Voce terá de:– No programa anterior:

• Criar um método que grave todos os objetos que estão dentro de um vector;

• Criar método que leia todos os objetos • Observação:

– O método readObject() não retorna null quando ele atinge o fim do arquivo. Quando chegou no final do arquivo, ele gera uma exceção do tipo java.io.EOFException.

– Assim, para ler todos os objetos do arquivo, você tem duas soluções:

• Guarde o número de objetos gravados no arquivo numa variável e depois utilize um for para ler os objetos do arquivo.

• Trate a exceção EOFException para saber quando chegou no final do arquivo.