Dienstag, 1. März 2011
Binärdateien bearbeiten mit Java (PR: 5A, 5B)
Entwickeln Sie sie eine Klasse
Der Parameter
Die Datensatznummer
Gelöschte Datensätze werden einfach als gelöscht markiert (s.u.) und müssen beim Anlegen neuer Datensätze zuerst verwendet werden (erst wenn kein gelöschter Datensatz existiert, wird die Datei vergrößert).
Datensätze sollen gesperrt werden können (die Klasse
Die Strings sind kodiert mit dem Encoding ISO-8859-1, d.h. jedes Zeichen ist einem Byte kodiert und es sind nur ASCII-Zeichen sowie die westeuropäischen Erweiterungen erlaubt. Es gibt Strings fixer Länge (werden mit Leerzeichen aufgefüllt) und Strings variabler Länge (werden wie C-Strings mit
Die Datei mit den (Test-)Daten hat folgendes Format:
Die Datei beginnt mit einem Header:
Diese Datei enthält nur die Geräte (und deren grafische Koordinaten):
Schreiben Sie passende Tests um die Klasse
Die weiteren Tests sollen natürlich die gesamte Funktionalität und das Locking testen.
Nennen Sie das Projekt
Die Datenklasse soll dann später in einem Client-/Server-System zum Einsatz kommen, wo mehrere grafische Clients eine Binärdatei bearbeiten sollen. Die Angabe dazu folgt...
Data
, die das Interface DB
implementiert. Die Klasse Data
soll die Methoden zum Bearbeiten (Lesen, Schreiben) binärer Dateien nach dem unten beschriebenen Datenformat bereitstellen.package data; /** * RuD-Übung 2011 * * data.DB.java * @author (c) 2011, Harald R. Haberstroh * 1.3.2011 */ import java.rmi.Remote; import java.rmi.RemoteException; /** * @author Harald R. Haberstroh (hh) * */ public interface DB extends Remote { /** * Sperre den gegebenen Datensatz. Ist der Datensatz bereits gesperrt, dann * wait(). * * @param recNo * Nummer des zu sperrenden Datensatzes. * @return Sperr-Identifikation. * @throws RemoteException * @throws RecordNotFoundException * ungültige Datensatznummer */ public long lock(int recNo) throws RemoteException, RecordNotFoundException; /** * Hebe Sperre wieder auf. notify(). * * @param recNo * Nummer des gesperrten Datensatzes * @param lockCookie * Sperr-Identfikation. * @throws RemoteException * @throws RecordNotFoundException * ungültige Datensatznummer * @throws SecurityException * ungültiges lockCookie oder nicht gelockt */ public void unlock(int recNo, long lockCookie) throws RemoteException, RecordNotFoundException, SecurityException; /** * lege neuen Datensatz an. * * @param record * Neuer Datensatz * @return Nummer des neuen Datensatzes * @throws RemoteException */ public int create(Record record) throws RemoteException; /** * lösche Datensatz. Sperre wird aufgehoben, notify(); * * @param recNo * Nummer des Datensatzes. * @param lockCookie * Sperr-Identfikation. * @throws RemoteException * @throws RecordNotFoundException * ungültige Datensatznummer * @throws SecurityException * ungültiges lockCookie oder nicht gelockt */ public void delete(int recNo, long lockCookie) throws RemoteException, RecordNotFoundException, SecurityException; /** * ändere Datensatz (überschreibe mit dem gegebenen Datensatz). * * @param record * neuer Datensatz * @param recNo * Nummer des gesperrten Datensatzes * @param lockCookie * Sperr-Identfikation. * @throws RemoteException * @throws RecordNotFoundException * ungültige Datensatznummer * @throws SecurityException * ungültiges lockCookie oder nicht gelockt */ public void update(Record record, int recNo, long lockCookie) throws RemoteException, RecordNotFoundException, SecurityException; /** * suche Datensätze. * * @param criteria * String-Array mit Kriterien, null matcht alles, sonst * Stringrepräsentation des Suchkriteriums (entspricht den Daten in * Record). * @return Array von Recordnummern * @throws RemoteException */ public int[] find(String[] criteria) throws RemoteException; /** * lese Datensatz. * * @param recNo * Nummer des zu lesenden Datensatzes. * @return Record * @throws RemoteException * @throws RecordNotFoundException * Datensatz existiert nicht. */ public Record read(int recNo) throws RemoteException, RecordNotFoundException; }Die Klasse Data muss zusätzlich einen Konstruktor
Data(String dateiname)
bereitstellen, der die Datei dateiname (z.B. "machines.db"
) öffnet und zur Bearbeitung mit den im Interface DB
definierten Methoden bereitstellt. Der Konstruktor muss die nötigen Exceptions werfen, wenn die Datei nicht geöffnet werden kann.Der Parameter
String[] criteria
der Methode find()
enthält das Suchkriterium, wobei jedem Feld ein String zugeordnet ist. Soll also nur nach einem Namen (siehe unten) gesucht werden, so muss criteria[1]
den gesuchten Namen (bzw. einen Teil davon) enthalten. Alle anderen Elemente des Arrays müssen dann null
sein. Soll nach mehreren Kriterien selektiert werden, so sind die entsprechenden Felder mit Werten zu belegen.find()
liefert dann ein Array mit den Indizes der passenden Datensätze.Die Datensatznummer
recNo
ist immer der Index innerhalb der Datei!Gelöschte Datensätze werden einfach als gelöscht markiert (s.u.) und müssen beim Anlegen neuer Datensätze zuerst verwendet werden (erst wenn kein gelöschter Datensatz existiert, wird die Datei vergrößert).
RecordNotFoundException
wird immer dann geworfen, wenn recNo
auf einen gelöschten Datensatz weist oder, wenn der Datensatz gar nicht existiert. Lösen Sie das Problem, dass nur mit der einfachen RecordNotFoundException
das Dateiende nicht ermittelt werden kann, in geeigneter Weise.Record
muss in geeigneter Weise implementiert werden.Datensätze sollen gesperrt werden können (die Klasse
Data
kann von mehreren parallelen Threads verwendet werden). Dazu soll die Methode lock()
eine (beliebige) dem Datensatz zuordenbare Zahl (Lockcookie bzw. Sperr-Identifikation) liefern und den Satz sperren. Die Methoden, die eine Sperre benötigen müssen dann anhand dieses Lockcookies überprüfen, ob der Datensatz gesperrt ist und die entsprechende Operation ausführen. Ist der Datensatz nicht gesperrt oder das Lockcookie ungültig, so ist eine SecurityException
zu werfen. Die Methode unlock()
hebt die Sperre wieder auf. Nach einem delete()
braucht man (kann man) kein unlock()
machen.Datenformat
Die Strings sind kodiert mit dem Encoding ISO-8859-1, d.h. jedes Zeichen ist einem Byte kodiert und es sind nur ASCII-Zeichen sowie die westeuropäischen Erweiterungen erlaubt. Es gibt Strings fixer Länge (werden mit Leerzeichen aufgefüllt) und Strings variabler Länge (werden wie C-Strings mit
'\0'
abgeschlossen) mit einer Obergrenze.Die Datei mit den (Test-)Daten hat folgendes Format:
Die Datei beginnt mit einem Header:
4 Bytes Magic Cookie, Wert 4242 4 Offset in Bytes zu den eigentlichen Daten 2 Bytes Anzahl Felder pro Datensatz Pro Feld gibt es folgenden Eintrag: 2 Bytes Länge Feldname n Bytes Feldname 2 Bytes Länge Feldbeschreibung n Bytes Feldbeschreibung für die Tabellenansicht 1 Byte Datentyp: 'F' ... fix, 'V' ... variabel, 'C' ... ein Zeichen 2 Bytes Feldlänge Nach den Feldbeschreibungen, d.h. ab dem Offset, finden sich die eigentlichen Datensätze gemäß der Beschreibungen im Header: 2 Bytes Flag Gelöscht (== 0 ... gelöscht, != 0 ... aktiv) n Bytes Daten gemäß der Datensatzbeschreibung
Testdatei machines.db
Diese Datei enthält nur die Geräte (und deren grafische Koordinaten):
Feldname | Feldbeschreibung | (maximale) Länge | Typ | Bemerkung |
id | Geräte-Id | 10 | String '\0' terminiert | z.B. "z23" |
name | Gerätename | 100 | String '\0' terminiert | Gerätebeschreibung, z.B. "Laderoboter Halle B" |
x | x | 5 | String fixe Länge | z.B. " 50" (vorne mit Leerzeichen aufgefüllt) |
y | y | 5 | String fixe Länge | z.B. " 200" |
Testen der Klasse Data
Schreiben Sie passende Tests um die Klasse
Data
zu testen. Der erste Test soll einfach die Datei machines.db
in lesbarer Form auf der Konsole ausgeben.Die weiteren Tests sollen natürlich die gesamte Funktionalität und das Locking testen.
Downloads
- Interface DB.java
- Testdatei machines.db
Abgabe
Nennen Sie das Projekt
klasse-name-data
also z.B. 5ad-meier-data
und checken Sie es am CVS ein. Termin wird noch bekanntgegeben.Wie geht's weiter
Die Datenklasse soll dann später in einem Client-/Server-System zum Einsatz kommen, wo mehrere grafische Clients eine Binärdatei bearbeiten sollen. Die Angabe dazu folgt...
Abonnieren Posts [Atom]
Kommentar veröffentlichen