TableDescriptor



  • Ich häng immer noch ein bisschen bei dem doofen FileWizard Prog, und die Zeit drängt.

    Hab jetzt das Design der FileWrapper Lib etwas verändert:
    Zuerst einmal, in der Datei wird die Tabelle folgendermassen gespeichert:

    7;8
    fffisss
    Datensatz1
    Datensatz2
    Datensatz3
    ...
    Datensatz8 EOF
    

    7;8 // Will heißen, dass ein Datensatz aus 7 Feldern aufgebaut ist
    // Anhand des Semikolons soll der Konstruktor ablesen können,
    // wie der FieldSeparator aussieht
    // Die anschließende '8' gibt dem Konstruktor Auskunft darüber,
    // wieviele Datensätze es insgesamt gibt

    fffisss // Hieraus soll sich der Konstruktor den Datentyp der Felder
    // herleiten können, was den Zugriff auf einzelne Einträge in
    // der Datei weiter optimieren soll
    // Anschließend folgen dann die Datensätze

    // Mein ursprünglichen Ansatz, eine komfortabel einsetzbare
    // Library zu entwickeln, hat mir ziemlich schnell selber nicht mehr
    // gefallen, und drum sieht das jetzt so aus:

    // Struktur die sich mit der Dateisignatur beschäftigt
    struct TableDescriptor{
     USHORT AmountOfFields;
     ULONG AmountOfRecords;
     UCHAR Separator;
     UCHAR* FieldtypeInterpreter;
     TableDescriptor(USHORT aofields,ULONG aorecords,UCHAR sep='\0');
    };
    
    // Klasse, die das Dateiformat .fwz für einen normalsterblichen Programmierer
    // komfortabel handhabbar machen soll
    class FileWizard{
     HFILE tablefile;
     TableDesc* Tdesc;
     // und so weiter und so fort
    };
    

    Ich bin wirklich am verzweifeln, denn die doofe Library soll in zwei Wochen fertig sein, und irgendwie bin ich mittlerweile der Meinung, dass mir da ein bisschen zu viel aufgebrummt wurde.

    BITTE, wenn ihr eine Website kennt, bei der es zumindest Teile einer sehr ähnlichen Library zu finden gibt, dann wär ich Euch SEHR dankbar.
    Oder wenn Euch dazu ein Konzept einfallen würde.
    FileWizard soll:
    - sicherstellen, dass Dateien, die damit angelegt werden, von anderen Anwen-
    dungen, die mit der Klasse arbeiten, prinzipiell IMMER interpretiert werden
    können
    - falls eine existierende Datei damit geöffnet wird, diese möglichst flexibel
    als .fwz interpretieren können
    - UND UND UND

    Danke für jede Hilfe!!! 😉



  • Mecnels schrieb:

    BITTE, wenn ihr eine Website kennt, bei der es zumindest Teile einer sehr ähnlichen Library zu finden gibt, dann wär ich Euch SEHR dankbar.
    Oder wenn Euch dazu ein Konzept einfallen würde.

    Das wäre sehr viel einfacher wenn du mal erwähnen würdest was dein "FileWizard" leisten soll/muss.

    [ot]

    Mecnels Sig schrieb:

    Bsp. für grammatisches Wissen: eine union ist eine spezielle class

    😕
    [/ot]



  • Also wenn ich deine Idee richtig interpretiere willst du ein File-Datenbanksystem schreiben. Ich kann nicht oft genug wiederholen, dass du _imho_ dazu eine Index-File brauchst.

    Diese Index-File dokumentiert exakt die Positionen in der Datenfile, wo die Datensätze stehen, etc. Sinn des Ganzen ist es wiederum, Operationen zu reduzieren, die zur Verschiebung großer Datenmengen innerhalb der Datei führen.
    D.h. es ist nicht schlimm wenn innerhalb der Datenfile mal eine größere Zahl an Leerzeichen steht, die Platz für eine mögliche Vergrößerung eines Datensatzes bietet.

    Beispiel:

    Mitten in deiner Datenfile steht "blubb", Position, Länge und die Bedeutung von "blubb" sind in der Index-File dokumentiert. Direkt nach "blubb" folgen bereits die nächsten Daten. Nun wird "blubb" durch "superblubb" ersetzt, also müsstest du aufgrund der 5 neuen Zeichen ("super") alles was nach blubb in der File kommt verschieben, was bei sehr großen Datenfiles sehr aufwendig ist. Stattdessen füllst du aber das alte "blubb" mit Leerzeichen und updatest die Index-File bzgl. der Datenposition des alten "blubb" auf das neue "superblubb". "superblubb" steht aber nun am Dateiende, dadurch musste nichts verschoben werden.

    Aufgeräumt (sinnlose Leerzeichen entfernen) wird, wenn der Server gerade nichts zu tun hat. Dann wird z.b. an der alten "blubb"-Position für 5 Zeichen mehr Platz gemacht und "superblubb" dort eingefügt, wobei selbstverständlich (wie immer) wieder die Index-File für die blubb-Position upgedatet wird.

    Dazu vielleicht noch eine dritte File, die Datentypen und Tabellenlayout repräsentiert, kannst du aber auch in die Index-File packen.
    Trennzeichen aller Art (auch '\n') sind imho antiquiert, du scheiterst spätestens bei Blobs mit dieser Strategie.

    Aber mich bewegt weiterhin die Frage, warum du nicht sqlite nimmst 😕?

    edit: Beispielsweise könnte die Index-File so aufgebaut sein:

    tabellenname:spalte:datentyp dateizeigerposition, datenlänge
    

    Um Komplikationen zu verhindern, dürfen Tabellen- und Spaltennamen keine ":" enthalten. Die Index-File kannst du auch für jede Table extra anlegen. Imgrunde hat jede Datenbank deines Systems eine extra Datenfile.

    Ich hoffe ich konnte dir irgendwie weiterhelfen.



  • die frage ist, was dein format hauptsächlich zu tun kriegen soll?
    werden viele leseoperationen darauf ausgeführt?
    werden datensätze eher eingefügt als geändert? wie siehts mit dem löschen aus?
    das system welches du benutzt ist gut für tabellen in denen nur datensätze eingefügt oder gelesen werden, bzw änderungen nur sehr selten durchgeführt werden müssen.
    ein weiterer punkt ist, ob strings gespeichert werden, oder nur zahlen?

    wenn du strings speicherst, hast du den nachteil, dass du auf der suche nach dem datensatz eine suchdauer von O(Zeilen*Spalten) hast, weil du nicht mal eben sizeof(Zeile) weiterspringen kannst(du weisst ja nichtmal, wie groß eine Zeile ist). Diese Suchdauer lässt sich nur mit einem Inhaltsverzeichnis verbessern ->IndexFile.



  • otze schrieb:

    IndexFile.

    Zuerst einmal: Besten Dank für Eure Tipps, vor allem die Idee mit der Indexfile hat mir wirklich weiter geholfen. Ich glaube, meine Klasse steht jetzt einigermassen, soweit sieht der Header jetzt so aus:

    #include<windows.h>
    #include<stdlib.h>
    #include<string.h>
    #include "fwzmodules.h"
    
    class FileWizard{
    protected:
    	HANDLE tablefile;
    	unsigned long filesize;
    	unsigned long byteswritten;
    	unsigned long* preventzero;
    
    	const unsigned short fieldsize;
    	const unsigned short stringlength;
    
    	bool creation_required;
    
    	// Members initialized by Prepare() or CREATE_TABLE()
    	unsigned short fieldamount;
    	char* typemask;
    	char dummy;
    	char limiter[2];
    	unsigned long firstbytelastrecord;
    	char* signaturebuffer;
    
    	// Members initialized by InitTable()
    	unsigned short signaturelength;
    	unsigned long recordlength;
    	unsigned long recordamount;
    	unsigned long* RecordTable
    	char* LineBuffer;
    	char** FieldBuffer;
    	unsigned long CurrentRecord;
    
    	// Fills a given buffer with dummies
    	bool DummyBuffer(char* buffer_to_dummy,unsigned long buffersize);
    
    	/* Prepares FileWizard for its operations with an existing
    	   FileWizard-Table */
    	bool Prepare();
    
    	/* A Sub-Procedure of Prepare(), Prepare reads the file's most important
    	   properties from its signature, InitTable() calculates the other class
    	   members' values - won't need to Read any further data from the file */
    	bool InitTable();
    
    	/* Fills Fieldbuffers with Strings, a very important sub-procedure for
    	   various functions, especially for queries */
    	bool FillFieldBuffers();
    
    	/* Also a pretty important sub-procedure */
    	bool UpdateFileSize();
    
    	/* Constructs the Current Signature of the tablefile and Writes the signature-
    	   buffer to the file */
    	bool CreateSignature();
    
    public:
    	FileWizard(char* tfilename);
    	virtual ~FileWizard();
    
    	// desired_mask is a null-terminated string, that specifies
    	// the datatypes of the fields _ 'r' = 'Real Number', 'i' = 'Integer',
    	// 'se' = 'String' _ the function will fail if you try to Create a Table
    	// from an invalid typemask, Example for a valid typemask: "seserrse"
    	// which means: String-String-Real-Real-String, automatically selects
    	// the first record of the table for insertions
    	bool CREATE_TABLE(char* desired_mask);
    
    	// writes the content of the current LineBuffer To the File but won't
    	// increase CurrentRecord (the record remains selected for operations)
    	// One of FileWizard's most important functions
    	bool WRITE_LINE();
    
    	// This will save the Current Record to the tablefile as well as add a new
    	// record to the tablefile to the table + make this new record the selected record
    	bool ADD_RECORD();
    
    	// This function will delete a selected record as well as all data its stringfields
    	// refer to
    	bool DELETE_RECORD();
    
    	// inserts data to a field of the current record, the function fails
    	// if the datatype does not match the specifications of the table's typemask
    	// note that these functions won't write any data to the file, to do so call
    	// WRITE_LINE or ADD_RECORD
    	bool INSERT(char* Data,unsigned short fieldID);
    	bool INSERT(int Data,unsigned short fieldID);
    	bool INSERT(double Data,unsigned short fieldID);
    
    	// selects a record which contains a field with the QueryData for operations,
    	// the function fails if there is no record that contains the QueryData or
    	// if fieldID > fieldamount
    	bool SELECT(unsigned short fieldID,char* QueryData);
    	bool SELECT(unsigned short fieldID,int QueryData);
    	bool SELECT(unsigned short fieldID,double QueryData);
    
    	// These functions will create an extra table file that contains
    	// a copy of all records that matched your QueryData
    	// the return value is a nullterminated string that specifies the filename
    	// of the new tablefile
    	char* SELECTALL(unsigned short fieldID,char* QueryData);
    	char* SELECTALL(unsigned short fieldID,int QueryData);
    	char* SELECTALL(unsigned short fieldID,double QueryData);
    
    	// selects a record by its unique identifier, will fail if recordID > recordamount
    	bool SELECT(unsigned long recordID);
    
    	// simply creates a copy of the current tablefile, returns the filename of the
    	// copied tablefile
    	char* SELECTALL();
    
    	/* TODO: not yet implemented
    	virtual bool CREATE_VIEW(HANDLE*,unsigned long* AmountOfHandles);
    	virtual bool SHOW_SELECTION();
    	bool ADD_FIELD(unsigned short fieldposition,char* fieldtype);
    	bool DELETE_FIELD(unsigned short fieldposition);*/
    };
    
    class FileWizardUI:public FileWizard{
    };
    

    Tja, und zu meiner Schande muss ich ehrlich gestehen dass DB nicht so ganz meine Stärke sind (um ehrlich zu sein das ist mein erstes Projekt diesen Typs). Was jetzt nicht mehr in meine Zuständigkeit fällt ist die Erzeugung eines UI, das soll jetzt jemand anderer machen (Gott sei Dank! Wär das auch noch nötig gewesen wär ich sicher nicht mehr rechtzeitig fertig geworden). Nur dieser jemand andere soll jetzt mit meiner Klasse hier arbeiten können, und ich weiß nicht so recht, ob ich irgend etwas Wichtiges übersehen habe, was ich auf jeden Fall noch implementieren sollte. Die Funktionen CREATE_VIEW und auch ADD_FIELD hängen glaube ich stark mit dem UI zusammen, deshalb lass ich den Spass meinem Ersatzmann, und in meiner Klasse sind das Dummy-Funktionen.

    Bitte: Wenn Euch irgend eine entscheidende Schnittstelle auffällt, die hier fehlt, sagt es mir, damit ich sie bis Montag noch implementieren kann.

    Vorweg gleich nochmal Danke für Eure Mühe 🕶



  • Und was kann deine Psychoklasse jetzt eigentlich besser als sqlite? GAR NICHTS! Wohl eher einfach alles schlechter. Erfind doch das Rad nicht neu! Schau erst mal auf sqlite.org vorbei, dann ersparst du dir son Schwachsinn.
    tsssssssssss



  • Mecnels schrieb:

    Tja, und zu meiner Schande muss ich ehrlich gestehen dass DB nicht so ganz meine Stärke sind (um ehrlich zu sein das ist mein erstes Projekt diesen Typs). Was jetzt nicht mehr in meine Zuständigkeit fällt ist die Erzeugung eines UI, das soll jetzt jemand anderer machen (Gott sei Dank! Wär das auch noch nötig gewesen wär ich sicher nicht mehr rechtzeitig fertig geworden). Nur dieser jemand andere soll jetzt mit meiner Klasse hier arbeiten können, und ich weiß nicht so recht, ob ich irgend etwas Wichtiges übersehen habe, was ich auf jeden Fall noch implementieren sollte. Die Funktionen CREATE_VIEW und auch ADD_FIELD hängen glaube ich stark mit dem UI zusammen, deshalb lass ich den Spass meinem Ersatzmann, und in meiner Klasse sind das Dummy-Funktionen.

    Bitte: Wenn Euch irgend eine entscheidende Schnittstelle auffällt, die hier fehlt, sagt es mir, damit ich sie bis Montag noch implementieren kann.

    Vorweg gleich nochmal Danke für Eure Mühe 🕶

    Kann man vielleicht den Code für die Implementierung deiner Funktionen einmal ansehen? Die Idee ist ja nicht schlecht, eine DB objektorientiert mit SQL-ähnlichen Kommandos ansprechen zu wollen, aber ich glaub einfach nicht, dass irgendeine deiner Funktionen auch nur annähernd das tut, was du in den Kommentaren verheißt, bevor ich nicht wengistens die eine oder andere Implementierung gesehen habe! Und nein, das Einfügen neuer Felder hat nichts mit dem User Interface zu tun, das ist auf jeden Fall dein Problem.


Anmelden zum Antworten