Baixe o app para aproveitar ainda mais
Prévia do material em texto
CCT220 Aula 15: Arquivos, fluxos e serialização de dados Prof. Laércio Baldochi Introdução Em Java, um arquivo é tratado como um fluxo sequencial de dados Cada arquivo acaba com um marcador de fim de arquivo ou em um número específico de bytes registrado em uma estrutura de dados mantida pelo sistema Um programa Java abre um arquivo através da criação de um objeto e da associação de um fluxo de bytes a esse objeto Introdução Fluxos de bytes também podem ser associados a dispositivos Existem 3 objetos de fluxos associados a dispositivos System.in (entrada padrão. Ex: teclado) System.out (saída padrão. Ex: tela) System.err (fluxo de erro padrão. Ex: tela) Importante Todas as operações de i/o em Java requerem tratamento de exceção Fluxos (streams) São responsáveis por ler e escrever seqüências de bytes da memória para um arquivo de dados Processam dados no formato UNICODE Código universal que fornece um número único para tratar caracteres em todas as plataformas Fluxos (streams) Objetos do tipo stream podem ler e escrever uma seqüência de bytes tanto de um arquivo para um programa quanto de um programa para um arquivo, em tempo de execução São representados pelas classes abstratas InputStream (leitura) OutputStream (escrita) Pacote java.io provê as classes para entrada e saída de dados Hirarquia de classes do pacote java.io Java.java.io File FileDescriptor InputStream ByteArrayInputStream FileInputStream FilterInputStream BufferedInputStream DataInputStream PushBackInputStream ObjectInputStream PipedInputStream SequenceInputStream OutputStream ByteArrayOutputStream FileOutputStream FilterOutputStream BufferedOutputStream DataOutputStream PrintStream ObjectOutputStream PipedOutputStream RandomAccesFile Reader BufferedReader LineNumberReader CharArrayReader FilterReader PushbackReader InputStreamReader FileReader PipedReader StringReader Writer BufferedWriter CharArrayWriter FilterWriter OutpurStreamWriter FileWriter PipedWriter PrintWriter StringReader Serialização de objetos Técnica pela qual um objeto é representado por uma seqüência de bytes Permite armazenar objetos Java em um formato particular de arquivo Grande parte das classes da API Java são serializáveis Classes não serializáveis podem se tornar serializáveis implementando os métodos da interface java.io.Serializable A implementação de métodos prototipados nesta interface permite que objetos possam ser gravados e recuperados por streams especializadas Serialização de objetos Permite persistir objetos biblioteca para serialização de objetos permite a escrita genérica de objetos em um stream Serializar um objeto significa definir qual a ordem de gravação dos dados do objeto e qual a ordem de leitura para reconstrução do objeto em uma nova instância do mesmo Gravação de um objeto serializável Para gravar um objeto serializável utiliza-se uma classe do pacote java.io chamada ObjectOutputStream, que funciona como uma camada sobre um stream de bytes Para gravar o objeto serializável, utiliza-se o método writeObject() da classe ObjectOutputStream Exemplo : ... FileOutputStream f = new FileOutputStream(“arq.ext"); ObjectOutputStream s = new ObjectOutputStream(f); s.writeObject(“Hoje"); s.writeObject(new Date()); s.flush(); arq.ext f s “Hoje” “31/11/2003” Arquivo FileOutputStream ObjectOutputStream Nossos Objetos Leitura de um objeto serializável Para ler um objeto serializável utiliza-se uma classe do pacote java.io chamada ObjectInputStream, que funciona como uma camada sobre uma stream de bytes Para ler o objeto serializável, utiliza-se o método readObject() da classe ObjectInputStream Exemplo : ... FileInputStream in = new FileInputStream(" arq.ext "); ObjectInputStream s = new ObjectInputStream(in); String today = (String) s.readObject(); Date date = (Date) s.readObject(); arq.ext in s “Hoje” “31/11/2003” Arquivo FileInputStream ObjectInputStream Nossos Objetos Para tornar um objeto serializável... 1) Declara-se a classe com implements Serializable; 2) Implementa-se um método que possibilite persistir o objeto (serialização) 3) Implementa-se um método que possibilite realizar a desserialização, ou seja, recuperar o arquivo e reconstruí-lo em memória numa nova instância do objeto 4) Deve-se respeitar a regra de operações CRUD (Create, Read, Update e Delete), as quais devem ficar associadas a classes controladoras Dicas Certos membros de dados não devem ser serializados Ex: Manipuladores de arquivos ou de janelas que só tem significado para métodos nativos A linguagem Java fornece um mecanismo para evitar que tais campos sejam serializados. Basta marcá-los com a palavra chave transient Campos transient são sempre pulados quando os objetos são serializados Exemplo import java.io.Serializable; public class Disciplina implements Serializable { private int codigo; private String nome; private int cargaHoraria; public Disciplina(int pCodigo, String pNome, int pCargaHoraria) throws Exception { setCodigo(pCodigo); setNome(pNome); setCargaHoraria(pCargaHoraria); } //Métodos de atribuição public void setCodigo(int pCodigo) { codigo = pCodigo; } public void setNome(String pNome) { nome = pNome; } public void setCargaHoraria(int pCargaHoraria) throws Exception { if ((pCargaHoraria < 30) || (pCargaHoraria > 110)) { throw new Exception("A carga horária deve estar entre 30 e 110 horas."); } cargaHoraria = pCargaHoraria; } //Métodos de recuperação public int getCodigo() {return codigo; } public String getNome() { return nome; } public int getCargaHoraria() { return cargaHoraria; } } A classe Disciplina implementa a interface Serializable. import java.util.*; import java.io.*; public class ControleDisciplina { private final String arquivo = "disc.dat"; private Vector listaDisciplina = new Vector(); //Método de inserção public void insereDisciplina(int pCodigo, String pNome, int pCargaHoraria) throws Exception { Disciplina objDisc = new Disciplina(pCodigo, pNome, pCargaHoraria); listaDisciplina.add(objDisc); gravaDisciplinas(); } //Método de composição dos dados da disciplina utilizado para visualização private String getDisciplina(Disciplina objPDisciplina) { return "Código: " + objPDisciplina.getCodigo()+ " Nome: " + objPDisciplina.getNome()+ " Carga Horária: "+ objPDisciplina.getCargaHoraria()+"\n"; } //Método para obtenção das lista de disciplinas public String getListaDisciplinas() { String result = ""; Disciplina objDisciplina = null; for (int intIdx = 0; intIdx < listaDisciplina.size(); intIdx++) { objDisciplina = (Disciplina)listaDisciplina.elementAt(intIdx); result += getDisciplina(objDisciplina); } if (result.equalsIgnoreCase("")) return "Não existem disciplinas cadastradas."; else return result; } //Método para obtenção de uma disciplina public String getDisciplina(int pCodigo) { Disciplina objDisciplina = null; for (int intIdx = 0; intIdx < listaDisciplina.size(); intIdx++) { objDisciplina = (Disciplina)listaDisciplina.elementAt(intIdx); if (objDisciplina.getCodigo() == pCodigo) return getDisciplina(objDisciplina); } return "Não foi encontrada nenhuma disciplina com o código "+pCodigo+"."; } public void gravaDisciplinas() throws Exception { FileOutputStream objFileOS = new FileOutputStream(arquivo); ObjectOutputStream objOS = new ObjectOutputStream(objFileOS); objOS.writeObject(listaDisciplina); objOS.flush(); objOS.close(); } public void recuperaDisciplinas() throws Exception { File objFile = new File(arquivo); if (objFile.exists()){ FileInputStream objFileIS = new FileInputStream(arquivo); ObjectInputStream objIS = new ObjectInputStream(objFileIS); listaDisciplina = (Vector)objIS.readObject(); objIS.close(); } } } Método utilizado para serializar a lista de disciplinas. Método utilizado para desserializar a lista de disciplinas. import javax.swing.*; public class LimiteDisciplina { //Instancia o Controlador private ControleDisciplina objCtrDisc = new ControleDisciplina(); public void capturaDados() { int escolha = 0; String escolhaInformada = ""; //Variáveis utilizadas para recuperar as informações da interface do usuário int codigo = 0; String nome = ""; int cargaHoraria = 0; try { objCtrDisc.recuperaDisciplinas(); do { do { try { escolhaInformada = JOptionPane.showInputDialog( "Escolha uma opção do menu:\n"+ "[1] Adiciona disciplina\n"+ "[2] Lista disciplinas\n"+ "[3] Finaliza"); escolha = Integer.parseInt(escolhaInformada); } catch (Exception exc) {} } while ((escolha < 1) || (escolha > 3)); Chama o método recuperaDisciplinas() que irá recuperar a lista de disciplinas. switch (escolha) { case 1: try { //Requisita o Código, Nome e Carga Horária codigo = Integer.parseInt(JOptionPane.showInputDialog ("Informe o código")); //Requisita o Nome nome = JOptionPane.showInputDialog ("Informe o nome"); //Requisita a Carga Horária cargaHoraria = Integer.parseInt(JOptionPane.showInputDialog ("Informe o carga horária")); //Adiciona o objeto para a lista de pacientes objCtrDisc.insereDisciplina(codigo, nome, cargaHoraria); } catch (Exception exc) { JOptionPane.showMessageDialog(null, exc.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } break; case 2: JOptionPane.showMessageDialog(null, objCtrDisc.getListaDisciplinas(), "Relação de Disciplinas", JOptionPane.INFORMATION_MESSAGE); break; case 3: System.exit(0); } } while (true); } catch (Exception exc) { JOptionPane.showMessageDialog(null, exc.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } } public static void main (String par[]) { LimiteDisciplina objLimDisc = new LimiteDisciplina(); objLimDisc.capturaDados(); } } Exercício 1 Complete o programa exemplo inserindo no menu uma opção responsável por salvar os dados do arquivo Para tanto, deve-se utilizar o método gravaDisciplinas da classe ControleDisciplina Exercício 2 Entrega: 20/10 Fazer a análise e implementação de um sistema que cadastre alunos, disciplinas e turmas. Primeiramente o usuário deve cadastrar alunos e disciplinas e depois poderá fazer o cadastro de turmas, que deve permitir a escolha da disciplina e seus respectivos alunos. Uma turma pode ter uma disciplina e vários estudantes. O sistema também deve permitir a visualização de todos os alunos, todas as disciplinas e as turmas, com suas respectivas disciplinas e alunos. As informações relacionadas a disciplinas, alunos e turmas devem ser armazenadas em arquivo (persistência). Informações de cada entidade: Estudantes: código, nome, matrícula Disciplinas: código, nome, carga-horária Turmas: código, nome da turma, código da disciplina e os códigos dos respectivos estudantes Exercício 2 (cont) Criar uma entidade para estudante, disciplina e turma; Cada entidade deve ser manipulada por um controlador, portanto deverá haver um controlador para estudante, disciplina e turma Qualquer interação do usuário com o sistema deve ser feito através de um limite. Como o usuário deverá cadastrar estudantes, disciplinas e turmas, automaticamente, um limite para cada uma das unidades será necessário Como o sistema tem mais de uma funcionalidade, é interessante ter um limite principal, para que o usuário escolha uma opção, e um controlador principal, que tem como funcionalidade fazer as chamadas aos demais controladores O cadastro de turmas deve permitir apenas escolha de disciplinas e estudantes já cadastrados (esse relacionamento pode ser feito através do código da disciplina e código do estudante). Diagrama de robustez Responsabilidades • Application: é a classe que implementa o método main e inicia a aplicação • ctrPrincipal: essa classe implementa o comportamento de um controlador. Cria 4 instâncias, conforme diagrama de robustez, chama a classe limPrincipal para montar o menu de opções e interagir com os demais controladores. • limPrincipal: essa classe é responsável por implementar o método que apresenta o menu e retornar a escolha para o ctrPrincipal. • limDisciplina: essa classe implementa o comportamento de um limite. Nessa classe deve haver um método que retorna uma lista contendo código, nome e carga-horária da disciplina cadastrada para o controlador de disciplina. • crtDisciplina: essa classe implementa o comportamento de um controlador. É nela que se encontra o Vector contendo a lista de disciplinas cadastradas pelo usuário. • entDisciplina: nessa entidade há necessidade de inserir os atributos código, nome e carga-horária da disciplina. Também é necessário criar os métodos gets e sets. • limEstudante: essa classe implementa o comportamento de um limite, que é responsável pelo cadastro de estudantes. Deve haver um método que retorna uma lista contendo o código, nome e matrícula. Responsabilidades ctrEstudante: esse controlador será o responsável pela criação da entidade estudante, que utiliza as informações requeridas na classe limite estudante. entEstudante: entidade responsável por armazenar as informações dos estudantes, que são o código, o nome e a matrícula. Deve implementar os métodos gets e sets. limTurma: essa classe implementa o comportamento de um limite, que é responsável pelo cadastro de uma turma. Deve haver um método que retorna o código da turma, nome da turma, código da disciplina e um vetor de códigos de estudantes. ctrTurma: esse controlador é o responsável pela criação da entidade turma, através do uso da classe limite turma. Deve haver um vetor para armazenar objetos da entidade turma. entTurma: entidade responsável por armazenar informações das turmas, que são o código da turma, seu nome, o código de uma disciplina e um vetor de códigos de estudantes. Deve implementar os métodos gets e sets. Diagrama de sequência Diagrama de sequência Diagrama de classe Slide 1 Slide 2 Slide 3 Slide 4 Slide 5 Slide 6 Slide 7 Slide 8 Slide 9 Slide 10 Slide 11 Slide 12 Slide 13 Slide 14 Slide 15 Slide 16 Slide 17 Slide 18 Slide 19 Slide 20 Slide 21 Slide 22 Slide 23 Slide 24 Slide 25 Slide 26 Slide 27
Compartilhar