Festplattenimage einlesen C/C++
-
Hallo Leute,
ich habe folgendes Problem. Wie kann ich am einfachsten bzw. effizientesten ein mehrere GB großes Festplattenimage zur Weiterverarbeitung in C++ einlesen? Letzten Endes möchte ich das Image auf diverse Bytestrukturen untersuchen. Hat damit jemand Erfahrung gemacht bzw. kennt evtl. eine Library?
Vielen Dank und Grüße
tommy
-
tommy0816 schrieb:
Wie kann ich am einfachsten bzw. effizientesten ein mehrere GB großes Festplattenimage zur Weiterverarbeitung in C++ einlesen? Letzten Endes möchte ich das Image auf diverse Bytestrukturen untersuchen.
Wie wäre es hiermit?
#include <algorithm> #include <fstream> #include <iterator> #include <vector> int main() { std::ifstream file("xyz.img",std::ios_base::binary); std::vector<unsigned char> image; file >> std::noskipws; std::copy( std::istream_iterator<unsigned char>(file), std::istream_iterator<unsigned char>(), std::back_inserter(image) ); }
-
out schrieb:
tommy0816 schrieb:
Wie kann ich am einfachsten bzw. effizientesten ein mehrere GB großes Festplattenimage zur Weiterverarbeitung in C++ einlesen? Letzten Endes möchte ich das Image auf diverse Bytestrukturen untersuchen.
Wie wäre es hiermit?
#include <algorithm> #include <fstream> #include <iterator> #include <vector> int main() { std::ifstream file("xyz.img",std::ios_base::binary); std::vector<unsigned char> image; file >> std::noskipws; std::copy( std::istream_iterator<unsigned char>(file), std::istream_iterator<unsigned char>(), std::back_inserter(image) ); }Das ist definitiv nicht effizient, sondern eher die ineffizienteste Art (abgesehen von absichtlichen Warteschleifen im Code). Nimm read und Konsorten. Als Datenstruktur kommt es drauf an, wie groß das Image ist und wie groß der Arbeitsspeicher ist. Prinzipiell klingt die Suche nach Mustern nach einem Fall für vector, eventuell deque (falls man an der Arbeitsspeicherkapazität kratzt). Festplattenimages sind aber in der Regel wesentlich größer als ein paar Gigabytes, da wird man sich wohl fragen müssen, ob es nicht auch in Frage käme, das Image stückchenweise zu betrachten. Ganz einlesen wird in der Regel aus technischen Gründen nicht möglich sein.
-
SeppJ schrieb:
Nimm read und Konsorten.
Meinst du so?
int main() { std::ifstream file("xyz.img",std::ios_base::binary); file.seekg(0,std::ios_base::end); unsigned length = file.tellg(); file.seekg(0,std::ios_base::beg); char* image = new char[length]; file.read(image,length); }
-
Ich verstehe zwar nicht, wieso du keinen vector nimmst, aber im Prinzip ja.
-
Würde das Ganze blockweise einlesen und auf Muster prüfen. Du musst allerdings den Sonderfall betrachten, dass ein Blockwechsel mitten im Muster auftreten kann.
-
Wieso genau musst du unbedingt das ganze Image in den Speicher laden? Wie schon angedeutet wurde, wird man wohl davon ausgehen müssen, dass so ein Festplattenimage potentiell wesentlich größer ist als der verfügbare Arbeitsspeicher!?
-
SeppJ schrieb:
Ich verstehe zwar nicht, wieso du keinen vector nimmst, aber im Prinzip ja.
readwill doch einchar*als Argument.vectorkann ich dann doch erst einsetzen, nachdem ichreadgemacht habe.
-
Sepp meint damit sowas:
#include <vector> #include <fstream> int main() { // open file std::ifstream file("hdd.img", std::ios::binary); // determine size file.seekg(0,std::ios_base::end); unsigned length = file.tellg(); file.seekg(0,std::ios_base::beg); // allocate buffer std::vector<char> buffer(length); // read data file.read(&(buffer[0]), length); }Vorteil ist hier, dass der vector den Speicher selbstständig wieder freigibt.
Du solltest aber weiterhin beachten, dass eben Festplatten-Images meistens größer sind als dein Arbeitsspeicher.
(Abgesehen davon, dass unsigned int sowohl bei x86 als auch x86_64 lediglich 32 Bit groß ist. Ist dein Image größer, so werden bei deiner length einfach die überschüssigen Bits weggeschnitten.)Sinnvoll wäre es, sich mit den Datenstrukturen auf einer Festplatte zu befassen (MBR, Dateisystem-Tabellen usw.). Diese enthalten Adressen von anderen wichtigen Datenblöcken im Image, sodass man gezielt nur die relevanten Blöcke laden kann.
-
Da das Einlesen der Datei vermutlich von einem langsamen Medium geschieht, ist das A und O hier die Minimierung der Dateizugriffe. Wenn ich
tommy0816 schrieb:
Letzten Endes möchte ich das Image auf diverse Bytestrukturen untersuchen.
richtig verstehe, empfiehlt sich daher eine Vorgehensweise, wie sie beispielsweise von GNU grep benutzt wird (siehe hier): Nur die Bytes holen, die man auch wirklich ankucken will. Habe ich beispielsweise eine 512 Byte lange Pattern und stelle fest, dass das Byte 512 Byte hinter meiner Position nicht passt, kann ich gleich 512 Byte weiterspringen.
Es gibt eine Reihe von Algorithmen, die sich für diesen Zweck anbieten und ein solches Vorgehen erlauben. GNU grep benutzt Boyer-Moore, und das könnte auch für dich eine gute Wahl sein. Letztendlich kann ich das aber aus der Enternung natürlich nicht mit Bestimmtheit sagen.
-
DrakoXP schrieb:
(Abgesehen davon, dass unsigned int sowohl bei x86 als auch x86_64 lediglich 32 Bit groß ist. Ist dein Image größer, so werden bei deiner length einfach die überschüssigen Bits weggeschnitten.)
std::streamsize FTW!