Problemas com RandomAccessFile

9 respostas
java
L

Estou desenvolvendo um código para um trabalho de faculdade onde preciso preencher dados e armazena-los em um ArrayList, depois disso, ai selecionar uma opção no menu, ela chama um objeto de uma outra classe para salvar todo o conteúdo do ArrayList dentro de um RandomAccessFile em txt. Fiz o código porém ao executa-lo, ele salva somente uma letra “y” dentro do arquivo aleatório ao em vez de salvar o conteúdo do ArrayList. Alguém sabe como arrumar?

Segue abaixo o código e as 3 classes. O que realmente importa e o que está com problema é o objeto salvaTodosAlunos()

Trocar o RandomAccessFile por outra coisa não é uma opção pois o trabalho da faculdade pede especificamente esse metodo

Classe GerenciaAluno

import java.io.*;
import java.util.ArrayList;

public class GerenciaAluno {

    private static ArrayList<Aluno> alunos = new ArrayList<Aluno>();

    public static void cadastrarAluno(Aluno a) {
        alunos.add(a);
    }

    public static Aluno buscaAluno(double RA) {
        
        for (Aluno a : alunos) {
            if (a.getRA()==RA) { 
                return a;
            }
        }
        return null;
    }

public static String imprimeTodosAlunos() {
     String saida = "";
    for (Aluno a : alunos){
        saida += "\n" + a.imprimeDadosAluno();
    }
    return saida;
}

public static String salvaTodosAlunos() throws FileNotFoundException, IOException {
    RandomAccessFile random = new RandomAccessFile("aluno.txt", "rw");
    for (int i = 0; i < alunos.size(); i = i + 9) {
          random.write(alunos.indexOf(i));         
    }
    return null;
}

public static int leTodosAlunos() throws FileNotFoundException, IOException {
    int retorno = 0;
    FileReader fr = new FileReader("aluno.txt");
    for (int i = 0; i < alunos.size(); i++) {
        retorno = fr.read();
    }
    fr.close();
    return retorno;
  }
}

Classe Aluno

public class Aluno {

    private String nome;
    private String cpf;
    private double RA;
    private String curso;

    public Aluno(String nome, String cpf, double RA, String curso) {
        this.nome = nome;
        this.cpf = cpf;
        this.RA = RA;
        this.curso = curso;
    }

    public Aluno() {
      this("","",0,"");
    }
    

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getCpf() {
        return cpf;
    }

    public void setCpf(String cpf) {
        this.cpf = cpf;
    }

    public double getRA() {
        return RA;
    }

    public void setRA(double RA) {
        this.RA = RA;
    }

    public String getCurso() {
        return curso;
    }

    public void setCurso(String curso) {
        this.curso = curso;
    }

    public String imprimeDadosAluno() {
        return "Nome do Aluno: " + this.nome + "\nCPF: " + this.cpf
                + "\nRA: " + this.RA + "\nCurso: " + this.curso + "\n==========";
    }

}

Classe principal TestaAluno

import java.io.FileNotFoundException;
import java.io.IOException;
import javax.swing.JOptionPane;

public class TestaAluno {

    public static void main(String[] args) throws FileNotFoundException, IOException, NumberFormatException {
        Aluno aluno;
        int opcao;

        do {

            opcao = Integer.parseInt(JOptionPane.showInputDialog(
                      "1 - Cadastrar Aluno\n"
                    + "2 - Buscar Aluno\n"
                    + "3 - Imprimir tudo\n"
                    + "4 - Salvar tudo \n"
                    + "5 - Ler tudo\n"
                    + "6 - Sair\n\n"
                    + "Escolha uma opção:"));

            switch (opcao) {

                case 1:
                    aluno = new Aluno();
                    aluno.setNome(JOptionPane.showInputDialog("Nome:"));
                    aluno.setCpf(JOptionPane.showInputDialog("CPF:"));
                    aluno.setRA(Long.parseLong(JOptionPane.showInputDialog("RA:")));
                    aluno.setCurso(JOptionPane.showInputDialog("Curso:"));
                    
                    GerenciaAluno.cadastrarAluno(aluno);
                    break;

                case 2:
                    double ra = Double.parseDouble(JOptionPane.showInputDialog("Digite o RA desejado:"));
                    
                    aluno = GerenciaAluno.buscaAluno(ra);
                    
                    if (aluno == null) {
                        JOptionPane.showMessageDialog(null, "Aluno não encontrado");
                    } else {
                        JOptionPane.showMessageDialog(null, aluno.imprimeDadosAluno());
                    }
                    break;

                case 3:
                    JOptionPane.showMessageDialog(null,GerenciaAluno.imprimeTodosAlunos());
                    break;

                case 4:
                    JOptionPane.showMessageDialog(null,"Arquivos Salvos"+GerenciaAluno.salvaTodosAlunos());
                    break;

                case 5:
                    JOptionPane.showMessageDialog(null,GerenciaAluno.leTodosAlunos());
                    break;

                case 6:
                    System.exit(0);
                    break;
                default:

            }

        } while (true);

    }
}

9 Respostas

S

salvaTodosAlunos() não é um objeto, é um método.

RandomAccessFile não é um método, é uma classe.

O método indexOf da interface List retorna o índice do objeto passado por parâmetro.
No seu caso vai retornar sempre -1, pois você está perguntando o índice da variável i.
Já o método write está gravando um byte no arquivo, esse byte é o valor retornado pelo indexOf.
Como a sua lista só possui um aluno, ele está gravando esse byte -1 uma única vez no arquivo.
De qualquer forma, você não quer gravar o índice de um objeto da lista, você quer gravar os alunos no arquivo.

O método read retorna o próximo byte lido, também não é o que você quer, você quer ler os objetos inteiros do arquivo.

Sugiro incluir os seguintes métodos na classe Aluno:

public static Aluno ler(DataInput entrada) throws IOException {
	Aluno aluno = new Aluno(); // um novo objeto será lido do arquivo
	aluno.setCpf(entrada.readUTF());
	aluno.setCurso(entrada.readUTF());
	aluno.setNome(entrada.readUTF());
	aluno.setRA(entrada.readDouble());
	return aluno;
}

public void escrever(DataOutput saida) throws IOException {
	Aluno aluno = this; // só pra ficar legível que é ESTE objeto que está se escrevendo no arquivo
	saida.writeUTF(aluno.getCpf());
	saida.writeUTF(aluno.getCurso());
	saida.writeUTF(aluno.getNome());
	saida.writeDouble(aluno.getRA());
}

E na classe GerenciaAluno implementar os métodos de leitura e escrita dessa forma:

public static void salvaTodosAlunos() throws IOException {
	RandomAccessFile random = new RandomAccessFile("aluno.txt", "rw");
	int quantidadeAlunos = alunos.size();
	random.writeInt(quantidadeAlunos); // assim saberá quantos alunos há pra ler no arquivo
	for (int i = 0; i < quantidadeAlunos; i++) {
		Aluno alunoPraSerEscrito = alunos.get(i);
		alunoPraSerEscrito.escrever(random); // objetos da classe Aluno sabem como se escrever no arquivo
	}
	random.close();
}

public static List<Aluno> leTodosAlunos() throws IOException {
	RandomAccessFile random = new RandomAccessFile("aluno.txt", "rw");
	int quantidadeAlunos = random.readInt(); // a primeira coisa gravada, foi a quantidade de alunos
	alunos = new ArrayList<>();
	for (int i = 0; i < quantidadeAlunos; i++) {
		Aluno alunoLido = Aluno.ler(random); // A classe Aluno sabe como ler um objeto do arquivo
		alunos.add(alunoLido);
	}
	random.close();
	return alunos;
}
L

Staroski, deu certo em partes, quando mando salvar o arquivo, os dados saem assim

[telefone removido] CCO LeoAgŒ)À
Sendo respectivo o CPF, Curso, Nome e o RA não aparece

E também quando mando ler este arquivo, ele retorna 0.

Alguma ideia?

S

Acho que você só implementou minha sugestão em partes, por isso não funcionou.

Digo isso pois, antes de gravar um aluno no arquivo, a primeira coisa a ser gravada era um int contendo a quantidade de alunos no arquivo e um int é gravado na forma de 4 bytes, ou seja, você teria que ter algum simbolo estranho no início do arquivo e não tem.

Também achei estranho es espaços em branco entre os campos, da forma como te implementei, isso não deveria ocorrer.

Para gravar os campos de texto, sugeri usar o método writeUTF, que, antes de gravar os caracteres, inclui 4 bytes que dizem quantos caracteres compõe a String, isso geraria uns símbolos estranhos no seu arquivo antes dos textos, e esses símbolos também não aparecem no trecho do arquivo que você postou.

O RA aparece sim, são aqueles símbolos estranho no final, se você olhar, o RA é gravado na forma de um double, ou seja, são 8 bytes no arquivo.

Posta o seu código que fica bem fácil de ver onde você se equivocou.
:slight_smile:

L

staroski, eu coloquei tudo… INclusive veio com os simbolos estranhos mas aqui não apareceram quando colei… Segue abaixo a clase GerenciaAluno. A classe Aluno está OK, coloquei o escrever e o ler conforme informado. Lembrando também que quando fui tentar ler esse arquivo, ele retornou [Aluno@“uma posição de memoria”]

import java.io.*;
import java.util.ArrayList;

public class GerenciaAluno {

    private static ArrayList<Aluno> alunos = new ArrayList<Aluno>();

    public static void cadastrarAluno(Aluno a) {
        alunos.add(a);
    }

    public static Aluno buscaAluno(double RA) {
        
        for (Aluno a : alunos) {
            if (a.getRA()==RA) { 
                return a;
            }
        }
        return null;
    }

    public static String imprimeTodosAlunos() {
         String saida = "";
        for (Aluno a : alunos){
            saida += "\n" + a.imprimeDadosAluno();
        }
        return saida;
    }

    public static String salvaTodosAlunos() throws FileNotFoundException, IOException {
        /*RandomAccessFile random = new RandomAccessFile("aluno.txt", "rw");
        for (int i = 0; i < alunos.size(); i++) {
              random.write(alunos.toString().indexOf(i));         
        }
        return null;*/
        RandomAccessFile random = new RandomAccessFile("aluno.txt", "rw");
    int quantidadeAlunos = alunos.size();
    random.writeInt(quantidadeAlunos); // assim saberá quantos alunos há pra ler no arquivo
    for (int i = 0; i < quantidadeAlunos; i++) {
        Aluno alunoPraSerEscrito = alunos.get(i);
        alunoPraSerEscrito.escrever(random); // objetos da classe Aluno sabem como se escrever no arquivo
    }
    random.close();
        return null;
    }

    public static ArrayList<Aluno> leTodosAlunos() throws FileNotFoundException, IOException {
        /*int retorno = 0;
        FileReader fr = new FileReader("aluno.txt");
        for (int i = 0; i < alunos.size(); i++) {
            retorno = fr.read();
        }
        fr.close();
        return retorno;       
        
        */
    RandomAccessFile random = new RandomAccessFile("aluno.txt", "rw");
    int quantidadeAlunos = random.readInt(); // a primeira coisa gravada, foi a quantidade de alunos
    alunos = new ArrayList<>();
    for (int i = 0; i < quantidadeAlunos; i++) {
        Aluno alunoLido = Aluno.ler(random); // A classe Aluno sabe como ler um objeto do arquivo
        alunos.add(alunoLido);
    }
    random.close();
    return alunos;
    }


        
}
S

Perfeito então! :slight_smile:

Evite usar ArrayList como o tipo de retorno do método, use a interface dele que é List
FileNotFoundException é uma IOException, não faz sentido declarar o throw das duas, declara só do IOException

Não, ele retornou um objeto do tipo aluno e você imprimiu o toString() do objeto aluno.
A implementação padrão do método toString() retorna [nome da classe]@[hash code]

Exemplo de como imprimir uma informação específica do aluno:

List<Aluno> alunosLidos = Aluno.leTodosAlunos(objetoRandomAccessFIle);
for (Aluno aluno : alunosLidos) {
    System.out.println("Nome do aluno: " + aluno.getNome() );
}
L

Entao… Tem q usar array list e na hora de ler, precisa ler do arquivo txt

S

Mas você faz um new ArrayList(), digo pra usar List no retorno do método e na declaração das variáveis.

L

Vou testar de novo… Consegue compartilhar seu codigo completo?

S

O código que escrevi, está lá em cima, não foi apagado do post
:slight_smile:

Olha como você está apresentando a lista de alunos:

JOptionPane.showMessageDialog(null,GerenciaAluno.leTodosAlunos());

Isso vai apresentar o toString() da lista de alunos retornada, não é o que você quer
Você quer informações uteis dos alunos
Se você tivesse uma tela especifica pra apresentar os dados dos alunos, seria mais fácil, mas você está usando JOptionPane, então não tem jeito, vais ter que criar uma String contendo as informações dos alunos

StringBuilder texto = new StringBuilder("Alunos:\n");
List<Aluno> alunosLidos = GerenciaAluno.leTodosAlunos();
for (Aluno lido : alunosLidos) {
    texto.append(aluno.getNome() + "\n" );
}
JOptionPane.showMessageDialog( null, texto.toString() );
Criado 20 de novembro de 2016
Ultima resposta 22 de nov. de 2016
Respostas 9
Participantes 2