Problema caricamento oggetto da file

di il
4 risposte

Problema caricamento oggetto da file

Salve a tutti ragazzi.

Premesso che sono un neofita della programmazione, sto sviluppando un progetto universitario e ho riscontrato un errore che non riesco a risolvere riguardo al caricamento di un oggetto da un file. Questo è il codice sorgente:

Main

	public static void main(String[] args) 
	{
		File file = new File("CarrieraUniversitaria.txt")
		Studente studente;
		if (file.exists())
		{
			studente = (Studente) caricaSingoloOggetto(file);
			if (studente != null)
			{
				System.out.println(MSG_FILE_CARICATO);
				//...altri metodi non rilevanti
			}
		}
		//...altri metodi non rilevanti
		salvaSingoloOggetto(file, studente);			
	}
Metodo caricamento oggetto da un file (caricaSingoloOggetto)
	
	public static Object caricaSingoloOggetto (File f)
	{
		Object letto = null;
		ObjectInputStream ingresso = null;
		try
		{
			ingresso = new ObjectInputStream(new BufferedInputStream(new FileInputStream(f)));
			letto = ingresso.readObject();
		}
		catch (FileNotFoundException excNotFound)
		{
			System.out.println(MSG_NO_FILE + f.getName());
		}
		catch (IOException | ClassNotFoundException excLettura)
		{
			System.out.println(MSG_NO_LETTURA + f.getName());
		}
		finally
		{
			if (ingresso != null)
			{
				try 
				{
					ingresso.close();
				}
				catch (IOException excChiusura)
				{
					System.out.println(MSG_NO_CHIUSURA + f.getName());
				}
			}
		} 
		return letto;
	} 
Metodo salvataggio oggetto su un file (salvaSingoloOggetto)

	public static void salvaSingoloOggetto (File f, Object daSalvare)
	{
		ObjectOutputStream uscita = null;
		try
		{
			uscita = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
			uscita.writeObject(daSalvare);
		}
		catch (IOException excScrittura)
		{
			System.out.println(MSG_NO_SCRITTURA + f.getName());
		}
		finally
		{
			if (uscita != null)
			{
				try 
				{
					uscita.close();
				}
				catch (IOException excChiusura)
				{
					System.out.println(MSG_NO_CHIUSURA + f.getName());
				}
			}
		} 
	}
Quello che accade è che riesco a salvare senza problemi l'oggetto Studente nel file, ma al successivo avvio il programma rileva un IOException mostrandomi il relativo messaggio di errore MSG_NO_LETTURA e non riesce a caricare con successo l'oggetto precedentemente salvato.

Qualche idea che mi aiuti a risolvere questo errore?

4 Risposte

  • Re: Problema caricamento oggetto da file

    Puoi mostrare Studente (ed altro associato rilevante)?
  • Re: Problema caricamento oggetto da file

    Assolutamente sì. Aggiungo che per cercare di risolvere il problema ho cercato di lavorare sul serialVersionUID, ma senza successo.

    Classe studente
    
    import it.ing.unibs.fp.MyUtil.Persona;
    import java.io.Serializable;
    import java.time.LocalDate;
    
    public class Studente extends Persona implements Serializable
    {
    	private String matricola;
    	private CorsoLaurea corsoLaurea;
    	
    	private final static String CODICE_MATRICOLA = "Codice di matricola: ";
    	private final static String CORSO_LAUREA = "Corso di laurea: ";
    
    	public Studente(String nome, String cognome, LocalDate dataNascita, String luogonascita, char genere, String telefono, String codiceFiscale, String matricola)
    	{
    		super(nome, cognome, dataNascita, luogonascita, genere, telefono, codiceFiscale);
    		this.matricola = matricola;
    	}
    
    	public String toString()
    	{
    		StringBuffer daRitornare = new StringBuffer();
    		daRitornare.append(super.toString());
    		daRitornare.append(" - " + matricola + " - " + corsoLaurea.toString());
    		return daRitornare.toString();
    	}
    
    	public String toStringFull()
    	{
    		StringBuffer daRitornare = new StringBuffer();
    		daRitornare.append(super.toStringFull());
    		daRitornare.append(CODICE_MATRICOLA + matricola + A_CAPO);
    		daRitornare.append(CORSO_LAUREA + corsoLaurea.toString() + A_CAPO);
    		return daRitornare.toString();		
    	}
    	
    	public String getMatricola() 
    	{
    		return matricola;
    	}
    	
    	public void setMatricola(String matricola) 
    	{
    		this.matricola = matricola;
    	}
    	
    	public CorsoLaurea getCorsoLaurea() 
    	{
    		return corsoLaurea;
    	}
    	
    	public void setCorsoLaurea(CorsoLaurea corsoLaurea) 
    	{
    		this.corsoLaurea = corsoLaurea;
    	}
    }
    
    Classe CorsoLaurea
    
    import java.io.Serializable;
    import java.util.Vector;
    
    public class CorsoLaurea implements Serializable
    {
    	private String nome;
    	private Vector<Corso> listaCorsi;
    	private Voto mediaDesiderata;
    	private Voto mediaPrevista;
    	private Voto mediaReale;
    
    	public CorsoLaurea (String nome, Vector<Corso> listaCorsi, Voto mediaDesiderata)
    	{
    		this.nome = nome;
    		this.listaCorsi = listaCorsi;
    		this.mediaDesiderata = mediaDesiderata;
    		calcoloMediaPrevista();
    	}
    	
    		public void calcoloMediaPrevista()
    	{
    		Vector <Corso> daFrequentare = listaCorsi;
    		int crediti = 0;
    		int mediaPrevista = 0;
    		
    		for (Corso corso : daFrequentare)
    		{
    			crediti += corso.getCrediti();
    			if (corso.esameSostenuto())
    			{
    				mediaPrevista += corso.getCrediti() * corso.getVoto().getVoto30();
    			}
    			else
    			{
    				mediaPrevista += corso.getCrediti() * corso.getVotoAtteso().getVoto30();
    			}
    		}
    		
    		mediaPrevista = mediaPrevista / crediti;
    		setMediaPrevista(new Voto(mediaPrevista, 30));
    	}
    		
    	public void calcoloMediaReale()
    	{
    		Vector <Corso> corsiSuperati = corsiSuperati();
    		int crediti = 0;
    		int mediaReale = 0;
    		
    		for (Corso corso : corsiSuperati)
    		{
    			crediti += corso.getCrediti();
    			mediaReale += corso.getCrediti() * corso.getVoto().getVoto30();
    		}
    		
    		mediaReale = mediaReale / crediti;
    		setMediaReale(new Voto(mediaReale, 30));
    	}
    		
    	public Vector<Corso> corsiSuperati ()
    	{
    		Vector<Corso> corsiSuperati = new Vector<>();
    		for (Corso corso : listaCorsi)
    		{
    			if (corso.esameSostenuto())
    			{
    				corsiSuperati.add(corso);	
    			}
    		}
    		return corsiSuperati;		
    	}
    		
    	public String toString() 
    	{
    		return nome.toUpperCase() + "\n";
    	}
    	
    	public String toStringFull() 
    	{
    		StringBuffer daRitornare = new StringBuffer();
    		daRitornare.append("\n" + nome.toUpperCase() + "\n\n");
    		daRitornare.append("Lista corsi da libretto\n\n");
    		for (Corso corso : listaCorsi)
    		{
    			daRitornare.append("- ");
    			daRitornare.append(corso.toString());
    			daRitornare.append("\n");
    		}
    		if (getMediaReale().getVoto30() != 0)
    		{
    			daRitornare.append("Media ponderata attuale: " + getMediaReale().getVoto30() + "/30" + " - " + getMediaReale().getVoto110() + "/110" + "\n");
    		}
    		daRitornare.append("Media ponderata prevista: " + getMediaPrevista().getVoto30() + "/30" + " - " + getMediaPrevista().getVoto110() + "/110" + "\n");
    		return daRitornare.toString();
    	}
    	
    	public String getNome() 
    	{
    		return nome;
    	}
    	
    	public void setNome(String nome) 
    	{
    		this.nome = nome;
    	}
    	
    	public Vector<Corso> getListaCorsi() 
    	{
    		return listaCorsi;
    	}
    	
    	public void setListaCorsi(Vector<Corso> listaCorsi) 
    	{
    		this.listaCorsi = listaCorsi;
    	}
    	
    	public Voto getMediaDesiderata() 
    	{
    		return mediaDesiderata;
    	}
    	
    	public void setMediaDesiderata(Voto mediaDesiderata) 
    	{
    		this.mediaDesiderata = mediaDesiderata;
    	}
    	
    	public Voto getMediaReale()
    	{
    		return mediaReale;
    	}
    	
    	public void setMediaReale(Voto mediaReale30) 
    	{
    		this.mediaReale = mediaReale30;
    	}
    
    	public Voto getMediaPrevista() 
    	{
    		return mediaPrevista;
    	}
    	
    	public void setMediaPrevista(Voto mediaPrevista) 
    	{
    		this.mediaPrevista = mediaPrevista;
    	}
    }
    
    Classe Corso
    
    import java.io.Serializable;
    import java.time.LocalDate;
    
    public class Corso implements Serializable
    {
    	private String nome;
    	private int crediti;
    	private LocalDate annoFrequenza;
    	private char semestreFrequenza;
    	private String stato;
    	private Voto voto;
    	private Voto votoAtteso;
    	
    	private final static String[] STATO_ESAME = {"Esame da sostenere", "Esame sostenuto"};
    
    	public Corso(String nome, int crediti, LocalDate annoFrequenza, char semestreFrequenza, Voto votoAtteso)
    	{
    		this.nome = nome;
    		this.crediti = crediti;
    		this.annoFrequenza = annoFrequenza;
    		this.semestreFrequenza = semestreFrequenza;
    		stato = STATO_ESAME[0];
    		this.votoAtteso = votoAtteso;
    	}
    	
    	public boolean esameSostenuto()
    	{
    		if (stato == STATO_ESAME [1])
    			return true;
    		else
    			return false;
    	}
    
    	public String toString() 
    	{
    		StringBuffer daRitornare = new StringBuffer();
    		daRitornare.append(nome.toUpperCase() + " - " + stato.toUpperCase());
    		if (voto != null)
    		{
    			daRitornare.append(voto.toString());
    		}
    		return daRitornare.toString();
    	}
    
    	public String toStringFull() 
    	{
    		StringBuffer daRitornare = new StringBuffer();
    		daRitornare.append(nome.toUpperCase() + " - " + crediti + " crediti\n");
    		daRitornare.append("Anno e semestre di frequenza: " + annoFrequenza.getYear() + ", " + semestreFrequenza + " semestre\n");
    		daRitornare.append(stato.toUpperCase() + "\n");
    		daRitornare.append("VOTO PREVISTO: " + votoAtteso.toString());
    		if (voto != null)
    			daRitornare.append("VOTO OTTENUTO: " + voto.toString());
    		return daRitornare.toString();
    	}
    	
    	public String getNome() 
    	{
    		return nome;
    	}
    	
    	public void setNome(String nome) 
    	{
    		this.nome = nome;
    	}
    	
    	public int getCrediti() 
    	{
    		return crediti;
    	}
    	
    	public void setCrediti(int crediti) 
    	{
    		this.crediti = crediti;
    	}
    	
    	public LocalDate getAnnoFrequenza() 
    	{
    		return annoFrequenza;
    	}
    	
    	public void setAnnoFrequenza(LocalDate annoFrequenza) 
    	{
    		this.annoFrequenza = annoFrequenza;
    	}
    	
    	public char getSemestreFrequenza() 
    	{
    		return semestreFrequenza;
    	}
    	
    	public void setSemestreFrequenza(char semestreFrequenza) 
    	{
    		this.semestreFrequenza = semestreFrequenza;
    	}
    	
    	public String getStato() 
    	{
    		return stato;
    	}
    	
    	public Voto getVoto() 
    	{
    		return voto;
    	}
    	
    	public void setVoto(Voto voto) 
    	{
    		this.voto = voto;
    		stato = STATO_ESAME[1];		
    	}
    	
    	public Voto getVotoAtteso()
    	{
    		return votoAtteso;
    	}
    	
    	public void setVotoAtteso(Voto votoAtteso) 
    	{
    		this.votoAtteso = votoAtteso;
    	}
    }
    
    Classe Voto
    
    import java.io.Serializable;
    import java.time.LocalDate;
    import java.time.format.DateTimeFormatter;
    
    public class Voto implements Serializable
    {
    	private Integer voto30;
    	private Integer voto110;
    	private String voto30L;
    	private String voto110L;
    	private LocalDate dataVoto;
    	
    	private final static Integer MAX_VOTO_30 = 30;
    	private final static Integer MAX_VOTO_110 = 110;
    	private final static String LODE = " e lode";
    
    	private final static String RICEVUTO = "RICEVUTO IL ";
    	
    	public Voto(int voto, int maxVoto, LocalDate dataVoto)
    	{
    		if (voto > maxVoto)
    		{
    			this.voto30 = MAX_VOTO_30;
    			this.voto110 = MAX_VOTO_110;
    			this.voto30L = MAX_VOTO_30.toString() + LODE;
    			this.voto110L = MAX_VOTO_110.toString() + LODE;			
    		}
    		else if (maxVoto == MAX_VOTO_30)
    		{
    			this.voto30 = voto;
    			this.voto110 = conversioneVoto(voto, MAX_VOTO_30, MAX_VOTO_110);		
    			this.voto30L = voto30.toString();
    			this.voto110L = voto110.toString();
    		}
    		else if (maxVoto == MAX_VOTO_110)
    		{
    			this.voto110 = voto;
    			this.voto30 = conversioneVoto(voto, MAX_VOTO_110, MAX_VOTO_30);
    			this.voto30L = voto30.toString();
    			this.voto110L = voto110.toString();
    		}
    		this.dataVoto = dataVoto;
    	}
    
    	public Voto(int voto, int maxVoto)
    	{
    		if (voto > maxVoto)
    		{
    			this.voto30 = MAX_VOTO_30;
    			this.voto110 = MAX_VOTO_110;
    			this.voto30L = MAX_VOTO_30.toString() + LODE;
    			this.voto110L = MAX_VOTO_110.toString() + LODE;			
    		}
    		else if (maxVoto == MAX_VOTO_30)
    		{
    			this.voto30 = voto;
    			this.voto110 = conversioneVoto(voto, MAX_VOTO_30, MAX_VOTO_110);			
    			this.voto30L = voto30.toString();
    			this.voto110L = voto110.toString();
    		}
    		else if (maxVoto == MAX_VOTO_110)
    		{
    			this.voto110 = voto;
    			this.voto30 = conversioneVoto(voto, MAX_VOTO_110, MAX_VOTO_30);
    			this.voto30L = voto30.toString();
    			this.voto110L = voto110.toString();
    		}
    	}
    
    	public static int conversioneVoto(int voto, int maxVoto, int maxVotoConvertito)
    	{
    		return (voto * maxVotoConvertito) / maxVoto;
    	}
    
    	public String toString()
    	{
    		StringBuffer daRitornare = new StringBuffer();
    		daRitornare.append(voto30L + " /" + MAX_VOTO_30 + " - " + voto110L + " /" + MAX_VOTO_110 + "\n");
    		if (dataVoto != null)
    		{
    			daRitornare.append(RICEVUTO + dataVoto.format(DateTimeFormatter.ofPattern("dd-MM-YYYY")));
    		}
    		return daRitornare.toString();
    	}
    	
    	public int getVoto30() 
    	{
    		return voto30;
    	}
    	
    	public void setVoto30(Integer voto30)
    	{
    		this.voto30 = voto30;
    	}
    	
    	public int getVoto110() 
    	{
    		return voto110;
    	}
    	
    	public void setVoto110(Integer voto110)
    	{
    		this.voto110 = voto110;
    	}
    	
    	public String getVoto30L()
    	{
    		return voto30L;
    	}
    	
    	public void setVoto30L(String voto30l) 
    	{
    		voto30L = voto30l;
    	}
    	
    	public String getVoto110L()
    	{
    		return voto110L;
    	}
    	
    	public void setVoto110L(String voto110l) 
    	{
    		voto110L = voto110l;
    	}
    
    	public LocalDate getDataVoto() 
    	{
    		return dataVoto;
    	}
    	
    	public void setDataVoto(LocalDate dataVoto)
    	{
    		this.dataVoto = dataVoto;
    	}
    }
    
  • Re: Problema caricamento oggetto da file

    ABolp ha scritto:


    public class Studente extends Persona implem ents Serializable
    {
    	private String matricola;
    	private CorsoLaurea corsoLaurea;
    	
    	private final static String CODICE_MATRICOLA = "Codice di matricola: ";
    	private final static String CORSO_LAUREA = "Corso di laurea: ";
    
    	public Studente(String nome, String cognome, LocalDate dataNascita, String luogonascita, char genere, String telefono, String codiceFiscale, String matricola)
    	{
    		super(nome, cognome, dataNascita, luogonascita, genere, telefono, codiceFiscale);
    		this.matricola = matricola;
    	}
    
    [....]
    
    Eccolo lì .... l'ho subito pensato!! Questo è un classico errore che rende la classe serializzabile ma NON deserializzabile.
    Il punto è che Studente è Serializable ma Persona (sebbene non l'hai postato) sicuramente NON lo è.
    Il fatto che Persona non sia serializzabile non sarebbe un problema (per la deserializzazione in sé) .... SE avesse un costruttore no-arg (senza argomenti). Peccato che Persona sicuramente NON ha un costruttore no-arg. Ne hai messo uno tu che riceve tutti quei parametri da Studente.

    A livello tecnico succede questo: quando deserializzi un oggetto es. Studente, essendo Studente Serializable, il suo costruttore NON viene invocato. L'obiettivo della deserializzazione NON è di invocare un costruttore della classe serializzabile ma di ri-ottenere uno stato precedentemente salvato.
    Però la classe Serializable può avere super-classi NON Serializable. Se questo succede, sulla PRIMA super-classe che trova non Serializable, su QUESTA classe viene invocato il costruttore. Ma ovviamente la deserializzazione non saprebbe nulla di quale costruttore scegliere, quindi si aspetta un costruttore no-arg.

    E attenzione: anche se in Persona (non Serializable) ci fosse un costruttore no-arg, solo la parte di "stato" in Studente verrebbe salvata. Lo stato che è in Persona lo perdi. Deve essere la classe serializzabile a farsi carico della serializzazione in modo "custom" per lo stato che appartiene a super-classi NON Serializable.
  • Re: Problema caricamento oggetto da file

    Fantastico sia nel risolvere l'errore, sia nella spiegazione del funzionamento della deserializzazione. Ho provato di tutto per risolvere il problema ma non avevo effettivamente mai pensato alla classe Persona in quanto si trova in un altro progetto.

    Ti ringrazio davvero tanto!
Devi accedere o registrarti per scrivere nel forum
4 risposte