Du bist hier: Startseite > Entwicklung (C/C++) > C++ Erweitert > Direkter Datenzugriff auf Binärdateien

Direkter Datenzugriff auf Binärdateien


Bytes laden anstatt Dateien ...


Direkter Zugriff auf Binärdateien


Der Zugriff auf die Daten einer Datei war im letzten Tutorial von C++ Grundlagen bisher immer seriell. Man musste erst die davor stehenden Daten lesen, um an die weiter hinten stehenden zu gelangen. Die Daten sind ja auf hintereinander liegenden Speicherplätzen der Festplatte angeordnet. Der Zugriff erfolgt dabei über einen Datenzeiger, der bei jedem Lesen und Schreiben automatisch weitergestellt wird.

Ein C++ Programmierer kann jedoch der PC Hardware ganz genau vorschreiben was sie zu tun und/oder zu lassen hat (Java ist im Vergleich dagegen noch nichtmal in der Lage, rauszufinden ob der Processor Virtuell ist oder nicht...!).Da der Datenzeiger der Festplattte nunmal Bestandteil der Hardware ist, können wir somit auch den Dateizeiger gezielt auf der Platte rumtanzen lassen. Üblicherweise benutzt man in C++ Binärdateien zur Verwaltung und Speicherung von Datensätzen. Mit dem direktem Zugriff auf bestimmte Daten einer Datei (ohne vorheriges Lesen vorstehender Daten) erreichen wir folgende Vorteile:

  • Maximale Geschwindigkeitsausnutzung - Nichts ist schneller
  • Durch die genaue Positionierung kommt nur das zurück was wir "bestellt" haben.
  • Gespeicherte und zurück geladene Binärdateien haben sich nicht verändert. Das bedeutet z.B., dass riesige, komplexe Datemstrukturen oder andere Benutzerdefinierte Datentypen (z.B. Objektorientierte Programmierung) nicht deserialisiert werden muss. In vielen Sprachen ist sowas unvorstellbar!
  • Man kann z.B. öffters Burnout´s mit 7200 UpM auf gleichen Position veranstalten. Die rasche Abnutzung hat den Nebeneffekt, dass die Platte frühzeitig an Altsheimer erkrannt und man ist gezwungen eine neue zu kaufen- Neu bedeutet oft schneller & besser!

Hierzu verfügt das Objekt fstream über die smarte Methode seekg()!
Im Beispiel gibt es eine Datenstruktur "datenStruktur". Direkt darunter wird ein Array mit genau diesem Typ erstellt und hat einem Index von 6! Somit haben wir jetzt eine Datenstruktur von der Größe 7 * 204 Bytes!


Datei:  Quelldateien/main.cpp
  1. #include <iostream> // std::cout, std::endl, std::cin
  2. #include <stdlib.h> // EXIT_SUCCESS
  3. #include <fstream> // std::fstream
  4. #include <string> // std::cin >>
  5. #include <conio.h> // getch()
  6.  
  7. using std::fstream;
  8. using std::system;
  9. using std::cout;
  10.  
  11. struct datenStruktur
  12. {
  13. char name[100]; // 100 Bytes
  14. char Nachname[100]; // 100 Bytes
  15. long nummer; // 4 bytes
  16. };
  17.  
  18. datenStruktur StrukturGruppe[] = {
  19. { "Meister", "Meier", 1 },
  20. { "Proper", "Nachname", 2 },
  21. { "MEISTERT", "Schroeder", 3 },
  22. { "Martin", "Krause", 4 },
  23. { "Marius", "Schmitz", 5 },
  24. { "frischer", "Hofmann", 6 },
  25. { "TonyStark", "Montana", 7 }
  26. }, rDatenStruktur;
  27.  
  28.  
  29. int main(void)
  30. {
  31. // Binärdatei zum Schreiben und Lesen öffnen
  32. fstream stream("StrukturGruppeArray.dat", std::ios::in | std::ios::out | std::ios::binary);
  33. if (stream.is_open())
  34. {
  35. // Vorzeichenlose Int Variable mit dem Wert ((204*7)/204) == 7! Errechnet die Anzahl
  36. // an datenStruktur im Array StrukturGruppe[]
  37. unsigned int uIStrukturArrayCount = (sizeof(StrukturGruppe) / sizeof(datenStruktur));
  38. // StrukturGruppenArray per Binäroperator übergeben
  39. // sowie die Gesamtgröße der StrukturGruppe in Bytes übergeben
  40. stream.write(
  41. (char*)&StrukturGruppe,
  42. uIStrukturArrayCount * sizeof(datenStruktur)
  43. );
  44. // Die gesamte Datenstruktur sollte jetzt auf deiner Platte neben deiner *.exe Datei
  45. // in "StrukturGruppeArray.dat" als Binärdatei gespeichert sein.
  46. // Falls das nicht geklappt hat, erstelle die Datei manuell!
  47.  
  48. // Auf Nutzereingabe warten, welche bestimmt welche von denn Verfügbaren Datenstrukturen
  49. // gezielt aus der StrukturGruppeArray.dat geladen werden soll
  50. unsigned int datenSatz;
  51. do
  52. {
  53. cout << "Datensatz anzeigem: [1-" << uIStrukturArrayCount << "]: ";
  54. std::cin >> datenSatz;
  55. } while (datenSatz < 1 || datenSatz > uIStrukturArrayCount);
  56. /*
  57. * Per fstream.write() haben wir eben das StrukturGruppe[] Array/Objekt binär nach StrukturGruppeArray.dat
  58. * kopiert. Die Gesamt Göße der StrukturGruppeArray.dat Datei müsste exakt 1428 Bytes betragen.
  59. * Mit fstream.read(...) kann der Inhalt der Datei wieder geladen werden. Bei einem einfachem Aufruf würde der
  60. * Dateizeiger am Anfang der Datei (Position 0 inerhalb der Datei) anfangen und sie bis zum Ende auslesen.
  61. * Mit der Methode fstream.seekg() können wir die Startposition ändern.
  62. * Angenommen du gibst 5 bei "Datensatz anzeigem" ein, sähe die Berechnung für denn Aufruf so aus:
  63. *
  64. * stream.seekg((5-1) * 204);
  65. *
  66. * Minus 1 wird gerecchnet, weil die niedrigste Eingabe bei "Datensatz anzeigem" als 1 angezeigt wurde. sie
  67. * aber in Wirklichkeit 0 ist. Die neue Rechnug sieht also so aus:
  68. *
  69. * stream.seekg(816);
  70. */
  71. stream.seekg((datenSatz - 1) * sizeof(datenStruktur));
  72. // Als nächstes wird fstream.read() ausgeführt.
  73. stream.read(
  74. (char*)&rDatenStruktur,
  75. sizeof(datenStruktur)
  76. );
  77. /*
  78. * Dem ersten Parameter wurde dem binärem Operator (char*) eine Referenz von rDatenStruktur übergeben.
  79. * Der zweite Parameter besagt, wieviele Bytes ausgelesen werden sollen. Hier wurden umgerechnet 204
  80. * übergeben was exakt eine Strukturgröße ist. Der Dateizeiger fängt also bei Byte 816 erst an und
  81. * liesst auch nur 204 Bytes bis zum 1020ten Byte. Die Strucktur wird durch die Referenz übertragen.
  82. *
  83. */
  84. stream.close();
  85. cout << "Name: " << rDatenStruktur.name << "\t\t" \
  86. << "Nachname: " << rDatenStruktur.Nachname << "\t";
  87. cout << "Nummer: " << rDatenStruktur.nummer << std::endl;
  88. }
  89. else
  90. {
  91. stream.clear();
  92. cout << "StrukturGruppeArray.dat konnte nicht geladen werden!" << std::endl;
  93. }
  94.  
  95. getch();
  96. return EXIT_SUCCESS;
  97. }

Kommentare zu diesem Beitrag

Sie müssen angemeldet sein, um eine Nachricht zu erstellen. Anmelden »