/* * record.java - Joris van Rantwijk * in2026 Inleiding databeheer * * Definitie van de recordformaten. */ import java.util.Date; import java.io.RandomAccessFile; import java.io.IOException; /* * Hier definieren we de twee recordtypen die we in de voorbeelden zullen * gebruiken (medewerker en afdeling). Per recordtype wordt een Java class * gedefinieerd, met daarin velden die overeenkomen met de relationele * definitie van het record, en methodes voor het lezen en schrijven van het * record in een file. * * We beginnen echter met het definieren van een Record class, die als * superclass voor de voorbeeld recordtypes wordt gebruikt. We gebruiken * dit later om bestandsorganisaties te beschrijven zonder vooraf te weten * welk recordtype gebruikt wordt. */ //=========================================================================== // Class Record // Dit is de superclass voor alle recordtypes. //=========================================================================== abstract class Record { // Sleutelwaarde van het record public int key; // Geef de omvang in bytes van het record in de file. // Deze is nodig voor het berekenen van de positie van records in de file. //----------------------------------------------------------------------- public abstract int getRecordlen(); // Lees het record uit de gegeven file. // Geef een exceptie als er iets fout gaat bij het lezen. //----------------------------------------------------------------------- public abstract void read(RandomAccessFile f) throws IOException; // Schrijf het record naar de gegeven file. // Geef een exceptie als er iets fout gaat bij het schrijven. //----------------------------------------------------------------------- public abstract void write(RandomAccessFile f) throws IOException; // Vertaal een string in een reeks bytes. Het eerste byte is de lengte // van de string, daarna volgen de karakters, aangevuld met nullen tot // maxlen. // Deze functie wordt gebruikt voor het opslaan van strings in de file. //----------------------------------------------------------------------- protected static byte[] strToBytes(String s, int maxlen) { byte[] result = new byte[maxlen]; if (s == null) { result[0] = 0; return result; } int i = (s.length() < maxlen) ? s.length() : maxlen - 1; s.getBytes(0, i, result, 1); result[0] = (byte) i; return result; } // Vertaal een reeks bytes in een string. Het eerste byte is de lengte // van de string, daarna volgen de karakters. // Deze functie wordt gebruikt voor het lezen van strings uit de file. //----------------------------------------------------------------------- protected static String bytesToStr(byte[] b) { return new String(b, 0, 1, b[0]); } // Construeer een nieuw record van het juiste type // Op deze manier kan een bestandsorganisatie worden geimplementeerd // zonder vooraf voor een bepaald record type te kiezen. //----------------------------------------------------------------------- public static Record newRecord(Class rectype) { try { return (Record)rectype.newInstance(); } catch (Exception e) { System.out.println(e); return null; } } } /* * Nu volgt de definitie van het recordtype 'medewerker' in de vorm * van de definitie van de class Medewerker. * Relationele definitie: * medewerker (m#, naam, adres, plaats, geboortedatum, functie, afd#) */ //=========================================================================== // Class Medewerker // // Het recordtype 'medewerker'. //=========================================================================== class Medewerker extends Record { // De velden van Medewerker komen overeen met de velden in de // relationele definitie // m# -> key public String naam; public String adres; public String plaats; public Date geboortedatum; public String functie; public int afd; // De maximale lengte (aantal karakters) van de stringvelden moet // vooraf worden vastgelegd. final static int NAAMLEN = 25; final static int ADRESLEN = 25; final static int PLAATSLEN = 25; final static int FUNCTIELEN = 15; // Opslag van velden in de file: // Integer velden in 4 bytes // String velden als een byte met de string-lengte, gevolgd door // een reeks bytes met de karakters van de string. // Date veld als 8 byte long met daarin het aantal msec sinds 1970. final static int recordlen = 4 + NAAMLEN + ADRESLEN + PLAATSLEN + 8 + FUNCTIELEN + 4; // Construeer een Medewerker met een ongeldige sleutel. //----------------------------------------------------------------------- public Medewerker() { key = -1; } // Construeer een Medewerker met de gegeven velden. //----------------------------------------------------------------------- public Medewerker(int m, String naam, String adres, String plaats, Date geboortedatum, String functie, int afd) { this.key = m; this.naam = naam; this.adres = adres; this.plaats = plaats; this.geboortedatum = geboortedatum; this.functie = functie; this.afd = afd; } // Geef de omvang in bytes van het record in de file. //----------------------------------------------------------------------- public int getRecordlen() { return recordlen; } // Lees een Medewerker uit de gegeven file. // Geef een exceptie als er iets mis gaat bij het lezen. //----------------------------------------------------------------------- public void read(RandomAccessFile f) throws IOException { byte[] t; // Integers kunnen direct ingelezen worden. key = f.readInt(); // String velden worden eerst in een byte-array gelezen, // en vervolgens in een String omgezet. t = new byte[NAAMLEN]; f.readFully(t); naam = bytesToStr(t); t = new byte[ADRESLEN]; f.readFully(t); adres = bytesToStr(t); t = new byte[PLAATSLEN]; f.readFully(t); plaats = bytesToStr(t); // De datum veld wordt eerst als long gelezen, en daarna // omgezet in een datum. geboortedatum = new Date(f.readLong()); t = new byte[FUNCTIELEN]; f.readFully(t); functie = bytesToStr(t); afd = f.readInt(); } // Schrijf een Medewerker naar de gegeven file. // Geef een exceptie als er iets mis gaat bij het schrijven. //----------------------------------------------------------------------- public void write(RandomAccessFile f) throws IOException { // Integer velden kunnen direct geschreven worden. f.writeInt(key); // String velden worden eerst omgezet in een reeks bytes. f.write(strToBytes(naam, NAAMLEN)); f.write(strToBytes(adres, ADRESLEN)); f.write(strToBytes(plaats, PLAATSLEN)); // De datum wordt omgezet in een long en daarna geschreven. if (geboortedatum == null) f.writeLong(0); else f.writeLong(geboortedatum.getTime()); f.write(strToBytes(functie, FUNCTIELEN)); f.writeInt(afd); } // Geef een string met alle gegevens uit het record. // Hiermee kan het record straks handig op het scherm worden gezet. //----------------------------------------------------------------------- public String toString() { return "m#: " + key + "\n" + "naam: " + naam + "\n" + "adres: " + adres + "\n" + "plaats: " + plaats + "\n" + "geboortedatum: " + geboortedatum + "\n" + "functie: " + functie + "\n" + "afd: " + afd + "\n"; } } /* * De definitie van het recordtype 'afdeling' is analoog aan die van * 'medewerker'. * Relationele definitie: * afdeling (afd#, afdnaam, telefoon, locatie, budget) */ //=========================================================================== // Class Afdeling // // Het recordtype 'afdeling'. //=========================================================================== class Afdeling extends Record { // De velden van Afdeling komen overeen met de velden in de // relationele definitie // afd# -> key public String afdnaam; public String telefoon; public String locatie; public int budget; // De maximale lengte (aantal karakters) van de stringvelden moet // vooraf worden vastgelegd. final static int NAAMLEN = 25; final static int TELLEN = 15; final static int LOCATIELEN = 15; final static int recordlen = 4 + NAAMLEN + TELLEN + LOCATIELEN + 4; // Construeer een Afdeling met een ongeldige sleutel. //----------------------------------------------------------------------- public Afdeling() { key = -1; } // Construeer een Afdeling met de gegeven velden. //----------------------------------------------------------------------- public Afdeling(int afd, String afdnaam, String telefoon, String locatie, int budget) { this.key = afd; this.afdnaam = afdnaam; this.telefoon = telefoon; this.locatie = locatie; this.budget = budget; } // Geef de omvang in bytes van het record in de file. //----------------------------------------------------------------------- public int getRecordlen() { return recordlen; } // Lees een Afdeling uit de gegeven file. // Geef een exceptie als er iets mis gaat bij het lezen. //----------------------------------------------------------------------- public void read(RandomAccessFile f) throws IOException { byte[] t; key = f.readInt(); t = new byte[NAAMLEN]; f.readFully(t); afdnaam = bytesToStr(t); t = new byte[TELLEN]; f.readFully(t); telefoon = bytesToStr(t); t = new byte[LOCATIELEN]; f.readFully(t); locatie = bytesToStr(t); budget = f.readInt(); } // Schrijf een Afdeling naar de gegeven file. // Geef een exceptie als er iets mis gaat bij het schrijven. //----------------------------------------------------------------------- public void write(RandomAccessFile f) throws IOException { f.writeInt(key); f.write(strToBytes(afdnaam, NAAMLEN)); f.write(strToBytes(telefoon, TELLEN)); f.write(strToBytes(locatie, LOCATIELEN)); f.writeInt(budget); } // Geef een string met alle gegevens uit het record. // Hiermee kan het record straks handig op het scherm worden gezet. //----------------------------------------------------------------------- public String toString() { return "afd#: " + key + "\n" + "afdnaam: " + afdnaam + "\n" + "telefoon: " + telefoon + "\n" + "locatie: " + locatie + "\n" + "budget: " + budget + "\n"; } } //=========================================================================== // End //===========================================================================