Kapitel 18. Serialisering af objekter

Kapitlet forudsættes af Kapitel 19, RMI.

Forudsætter Kapitel 15, Datastrømme og filhåndtering.

Når et program afslutter, kan det være, at man ønsker at gemme data til næste gang, programmet starter.

Man kan selvfølgelig skrive programkode, der gemmer og indlæser alle variablerne i de objekter, der skal huskes, men der findes en nemmere måde.

Java har en mekanisme, kaldet serialisering, der består i, at objekter kan omdannes til en byte-sekvens (med datastrømmen ObjectOutputStream), der f.eks. kan skrives til en fil [1]. Denne bytesekvens kan senere, når man har brug for objekterne igen, deserialiseres (gendannes i hukommelsen med datastrømmen ObjectInputStream). Dette kunne f.eks. ske, når programmet starter næste gang.

18.1. Hente og gemme objekter

Her er en klasse med to klassemetoder, der henter og gemmer objekter i en fil:

import java.io.*;
public class Serialisering
{
  public static void gem(Object obj, String filnavn) throws IOException
  {
    FileOutputStream datastrøm = new FileOutputStream(filnavn);
    ObjectOutputStream p = new ObjectOutputStream(datastrøm);
    p.writeObject(obj);
    p.close();
  }

  public static Object hent(String filnavn) throws Exception
  {
    FileInputStream datastrøm = new FileInputStream(filnavn);
    ObjectInputStream p = new ObjectInputStream(datastrøm);
    Object obj = p.readObject();
    p.close();
    return obj;
  }
}

Du kan benytte klassen fra dine egne programmer.

Her er et program, der læser en vektor fra filen [2] venner.ser, tilføjer en indgang og gemmer vektoren i filen igen.

import java.util.*;
public class HentOgGem
{
  public static void main(String arg[]) throws Exception
  {
    Vector v;
    try {
      v = (Vector) Serialisering.hent("venner.ser");
      System.out.println("Læst: "+v);
    } catch (Exception e) {
      v = new Vector();
      v.addElement("Jacob");
      v.addElement("Brian");
      v.addElement("Preben");
      System.out.println("Oprettet: "+v);
    }

    v.addElement("Ven"+v.size());
    Serialisering.gem(v,"venner.ser");
    System.out.println("Gemt: "+v);
  }
}

Resultatet bliver:

Oprettet: [Jacob, Brian, Preben]
Gemt: [Jacob, Brian, Preben, Ven3]

Første gang, programmet kører, opstår der en undtagelse, fordi filen ikke findes. Den fanger vi og tilføjer "Jacob", "Brian" og "Preben" til vektoren. Derpå tilføjer vi "Ven3" og gemmer vektoren.

Næste gang er uddata:

Læst: [Jacob, Brian, Preben, Ven3]
Gemt: [Jacob, Brian, Preben, Ven3, Ven4]

Køres programmet igen, ser man, at den hver gang tilføjer en indgang:

Læst: [Jacob, Brian, Preben, Ven3, Ven4]
Gemt: [Jacob, Brian, Preben, Ven3, Ven4, Ven5]

og

Læst: [Jacob, Brian, Preben, Ven3, Ven4, Ven5]
Gemt: [Jacob, Brian, Preben, Ven3, Ven4, Ven5, Ven6]

og

Læst: [Jacob, Brian, Preben, Ven3, Ven4, Ven5, Ven6]
Gemt: [Jacob, Brian, Preben, Ven3, Ven4, Ven5, Ven6, Ven7]

og

Læst: [Jacob, Brian, Preben, Ven3, Ven4, Ven5, Ven6, Ven7]
Gemt: [Jacob, Brian, Preben, Ven3, Ven4, Ven5, Ven6, Ven7, Ven8]

Hvis nogle af de serialiserede objekter indeholder datafelter, der er referencer til andre objekter, serialiseres disse også. Ovenfor så vi, at hvis man serialiserer en vektor, bliver elementerne i vektoren også serialiseret. Dette gælder også, hvis disse elementer selv indeholder eller er vektorer og så fremdeles, og så kan et helt netværk af objekter med indbyrdes referencer blive serialiseret. Man skal derfor være lidt påpasselig i sine egne programmer, det kan være, at man får for meget med.

Slutbemærkning:

[1]

Eller netværket for den sags skyld.

[2]

Man bruger ofte filendelsen .ser til serialiserede objekter.