Binärcode einer Datei auslesen und in einer Variable speichern
-
Hey Leute!
Ich hab zwar schon eine Möglichkeit in Perl gefunden, aber ich möchte es gerne mit C++ machen. Undzwar möchte ich ein Komprimierungsprogramm schreiben, mit einem selbstgeschriebenem Komprimierungsalgorithmus.
Das soll der Ablauf des Programms sein:
1. Benutzer gibt Pfad zur Datei ein
2. Der Binärcode der Datei wird in einer Variable gespeichert
3. Variable wird durch Komprimierungsalgorithmus komprimiert/umgeschrieben
4. Neue, komprimierte Datei wird gespeichertWär echt toll, wenn mir jemand helfen könnte.
//btw: Als OS habe ich im Moment nur Mac OS X 10.06 zur Verfügung, zu Hause aber auch Ubuntu 10.04 LTS
____________________________________
Meine Homepage
-
Upps, war grad ganz in Gedanken und hab die Hälfte vergessen^^
Naja^^
Also ich möchte nur wissen, wie ich von einer Datei den Binärcode auslesen kann, ich hab zwar schon gegoogelt, aber iwie nicht das richtige gefunden.
-
-
Wie kann man es schaffen, dies bei Google nicht zu finden?
Mit dem ios::binary flag beim Öffnen kannst du bewirken, dass die Datei binär gelesen wird. Danach aknnst du sie mit deiner Liblingsmethode einlesen, beispielsweise einfach mit copy in einen vector oder string schaufeln.
-
iwie bekomme ich trotz ios::binary nicht den Binärcode, sondern den Standard Text...
.txt's kann ich gar nicht öffnen, in .rtf's bekomm ich den Text der drin steht und von .rar's bekomm ich auch nicht den Binärceode
iwie bekomme ich die selben Ergebnisse als würde ich es so machen:
int value; ifstream file; file.open("test.rtf"); file >> value;
Hier mein Code:
#include <iostream> #include <fstream> #include <string> using namespace std; int main (int argc, char **argv) { int length; char* buffer; string value; ifstream file; file.open("Lorem ipsum.rtf", ios::binary); if(file.is_open() != true) { cerr << "Konnte Datei nicht oeffnen! \n"; return 1; } file.seekg (0, ios::end); length = file.tellg(); file.seekg (0, ios::beg); buffer = new char[length]; file.read(buffer, length); file.close(); cout.write(buffer, length); delete[] buffer; return 0; }
LG PAT
_________________________
http://p-remy.bplaced.de
-
Bevor wir uns jetzt ganz falsch verstehen: Beschreib mal bitte was du mit Binärcode meinst.
-
Um es genauer zu sagen, meine ich das Dualsystem oder Binärsystem, also die 0en und 1en die der Computer versteht.
Ich möchte durch den Komprimierungsalgorithmus z.B. folgendes machen:
Nehmen wir an, der Binärcode einer Datei lautet:
0100 0110 1001 0100 0110 1001
1110 0101 0111 1110 0101 0110
1110 0101 0111 1110 0101 0110
1110 0101 0111 1110 0101 0110
0100 0110 1001 0100 0110 1001
1110 0101 0111 1110 0101 0110
0100 0110 1001 0100 0110 1001
0100 0110 1001 0100 0110 10010100 0110 1001 0100 0110 1001
1110 0101 0111 1110 0101 0110
1110 0101 0111 1110 0101 0110
1110 0101 0111 1110 0101 0110
0100 0110 1001 0100 0110 1001
1110 0101 0111 1110 0101 0110
0100 0110 1001 0100 0110 1001
0100 0110 1001 0100 0110 10010100 0110 1001 0100 0110 1001
1110 0101 0111 1110 0101 0110
1110 0101 0111 1110 0101 0110
1110 0101 0111 1110 0101 0110
0100 0110 1001 0100 0110 1001
1110 0101 0111 1110 0101 0110
0100 0110 1001 0100 0110 1001
0100 0110 1001 0100 0110 1001Und der Komprimierungsalgorithmus ist (z.B.):
a = 0100 0110 1001
b = 1110 0101 0111Dann würde die Komprimierte Datei enthalten:
3*(2a 3*(2b) 2a 2b 2*(2a))
Das spart dann z.B. schon eine Menge Platz!
SoInfo: Da ich "auf Reisen" bin habe ich im Mom nur Mac OS X 10.06 und Ubuntu 10.04 LTS (demnächst vlt. 10.10) zur Verfügung.
Ich bin gerade erst am Lernen von C++, und dies soll ein kleineres Projekt sein, also Kritik zum Code ist erwünscht!
Danke schonmal an alle, die mir bereits geholfen haben und es werden!
LG PAT
______________________
http://p-remy.bplaced.de
-
Der Computer rechnet nicht in Nullen und Einsen. Er rechnet in Byte. Diese mögen intern vielleicht als eine Art Binärdarstellung existieren, aber da kommst du erst einmal nicht ran, es sei denn du rechnest deine Zahlen extra wieder in ein Binärsystem um (bei dem dann die Stellen wieder durch Bytes dargestellt würden).
-
Ich dacht der rechnet in Bits nicht in Bytes^^
Außerdem habe ich nie behauptet, dass der Computer damit rechnet, sondern lediglich, dass er es versteht.Jedenfalls möchte ich an den Binärcode der Datei, wie ich z.B. im Terminal mit folgendem Perl-Befehl dran komme:
perl -ne 'print unpack "B*", $_' Datei
Weiß denn keiner eine Lösung zu dem Problem? Ich dachte eig., dass das keine allzu schwere Frage sein kann^^
-
Du liest aus dem File eine Anzahl an
char
. Einchar
ist ein Zeichen und steht für ein Byte. Wenn du diese auf die Konsole schreibst, dann werden dort die Zeichen zum jeweiligen Byte (z.B. ASCII) ausgegeben und nicht die binäre Darstellung. Dein Denkfehler ist, dass wenn duchar
ausgibst, dass da automatisch eine binäre Darstellung erscheinen sollte. Dafür musst du selber sorgen, in dem du bei jedem Byte die binäre Darstellung ermittelst und ausgibst. Das machst du am besten, indem du mit den Bit-Operatoren die einzelnen Bits eines Bytes abfragst.Grüssli
-
Ich fürchte du verstehst nicht, wie ein Computer funktioniert. Es ist zwar auch kein großes Problem das was du da zeigst in C++ zu erreichen, aber dir ist glaube ich gar nicht klar, was das bedeutet. Ich kann dir im Rahmen des Forums aber auch nicht moderne Computertechnologie von Grund auf erklären.
Gegenfrage: Was für einen Unterschied macht es für deinen Kompressionsalgorithmus, wenn du anstatt
0100 0110 1001 0100 0110 1001 1110 0101 0111 1110 0101 0110
die Angabe
aabb
hast?
Wenn deine Antwort jetzt nicht "Das macht gar keinen Unterschied" ist, dann wird dein Algorithmus nicht funktionieren, weil er von völlig falschen Vorstellungen ausgeht.
-
SeppJ schrieb:
Wenn deine Antwort jetzt nicht "Das macht gar keinen Unterschied" ist, dann wird dein Algorithmus nicht funktionieren, weil er von völlig falschen Vorstellungen ausgeht.
... auf diese Idee wäre ich gar nicht gekommen, dass er so denken könnte ->
Ich bin sehr gespannt auf die AntwortGrüssli
-
Du meinst also, dass ich in einer Schleife den C-String (das char Array) teilweise in Binärcode umwandeln solle?
Also z.B. so?
char cstring[] = "Hallo Welt"; for(int i = 0; i < (sizeof(cstring) / sizeof(cstring[0])); i++) { cstring[i] = // Umwandlung in Binärcode }
(Bei der Gelegenheit könnte man direkt den C-String in String umwandeln)
Oder soll ich einen char (ein Byte) nochmal in die einzelnen Bits klein hacken und dann in Binärcode umwandenln? Da weiß ich nur noch nicht wie das geht..
Wär super nett, wenn mir jemand auch das noch erklären könnte!
-
Was soll denn "Binärcode" sein?
Der String"hallo"
liegt als Folge von 6 Bytes binär im Speicher. Da gibt es nichts umzuwandeln. Der Speicher ist sowieso immer binär aufgebaut.
Um an die einzelnen Bits zu kommen verwendet man Operatoren wie&
und<<
. Das sollte bei einer einfachen Komprimierung aber gar nicht notwendig sein.
-
Hm.. ich glaub ich hab deine Frage falsch verstanden, aber ich versuch sie trotzdem mal zu beantworten:
aabb ist ziemlich viel kürzer
0100 0110 1001 0100 0110 1001 1110 0101 0111 1110 0101 0110
-
[quote=TyRoXx]Was soll denn "Binärcode" sein?[/quote]
Hättest du alle Beiträge gelesen solltest du das wissen, denn diese Frage habe ich schoneinmal beantwortet^^
[quote=TyRoXx]Der String "hallo" liegt als Folge von 6 Bytes binär im Speicher. Da gibt es nichts umzuwandeln. Der Speicher ist sowieso immer binär aufgebaut. [...] Das sollte bei einer einfachen Komprimierung aber gar nicht notwendig sein.[/quote]
Wieso ich das will würdest du auch wissen, hättest du alle Beiträge gelesen (und verstanden!).
-
Folgendes Beispiel ist eine sehr einfache Komprimierung auf Byte-Ebene. Was ist jetzt der Unterschied zu deinem Verfahren?
#include <vector> #include <string> #include <iostream> #include <limits> typedef int short_can_hold_two_chars[sizeof(unsigned short) >= (2 * sizeof(unsigned char))]; std::vector<unsigned short> compress(const std::string &str) { std::vector<unsigned short> data; unsigned char count = 0; char last; for (size_t i = 0; i < str.size(); ++i) { const char current = str[i]; if ((i > 0) && (current != last) || (count == std::numeric_limits<unsigned char>::max())) { const unsigned short word = (((unsigned char)last) << 8) | count; data.push_back(word); count = 0; } last = current; ++count; } if (count > 0) { const unsigned short word = (((unsigned char)last) << 8) | count; data.push_back(word); } return data; } std::string uncompress(const std::vector<unsigned short> &data) { std::string str; for (size_t i = 0; i < data.size(); ++i) { unsigned short word = data[i]; unsigned char count = word & 0xff; unsigned char character = (word >> 8) & 0xff; str.append(count, character); } return str; } using namespace std; int main() { while (true) { string str; getline(cin, str); if (str.empty()) break; const vector<unsigned short> data = compress(str); cout << "Compressed: " << data.size() << (data.size() == 1 ? " word" : " words") << endl; const string test = uncompress(data); cout << "Test: " << test << endl; } }
-
Der Unterschied ist, dass dein Code für mich in großen Teilen unverständlich ist.
Ich möchte nicht Alternative bessere Lösungen haben, sondern einfach nur die Lösung für mein Problem.
-
//PAT// schrieb:
iwie bekomme ich trotz ios::binary nicht den Binärcode, sondern den Standard Text
[...]
Hier mein Code:int main (int argc, char **argv) { int length; char* buffer; string value; ifstream file; file.open("Lorem ipsum.rtf", ios::binary); if(file.is_open() != true) { cerr << "Konnte Datei nicht oeffnen! \n"; return 1; } file.seekg (0, ios::end); length = file.tellg(); file.seekg (0, ios::beg); buffer = new char[length]; file.read(buffer, length); file.close(); cout.write(buffer, length); delete[] buffer; return 0; }
Ist doch alles korrekt.
Wenn im File der Text "hallo" stehen und du diese als char* ausgibst, dann kommt logischerweise "hallo", weil zwischen dem text "hallo" und dem Binärcode von "hallo" kein Unterschied existiert.Wenn du eine Ausgabe von "10010011" willst, dann ist diese genauso lang wie "hallo du".
Das Zeichen '1' ist kein gesetzes Bit, sondern eine Zahl. Schau dir mal http://de.wikipedia.org/wiki/Ascii an.
-
Achso also bekomme ich mit dem Perl Befehl oben auch nur den ASCII Code heraus?
Hier steht, dass dies den Binärcode einer Datei ausgibt. Langsam steh ich auf dem Schlauch..
Aber ich glaub ich stell meine Frage mal anders: Wie kann ich eine Datei auslesen und sie komprimieren (bzw. zusammenfassen)? Bisher dachte ich, dass ich einfach den (wasauchimmerjetzt)Code der Datei hätte zusammenfassen können und in eine neue Datei hätte schreiben können, und bei der Dekomprimierung dann anhand der Datei die andere Datei wiederherstellen können. Mittlerweile, denke ich aber eher, dass das eher ein Verschlüsselungsverfahren wäre und keines Falls ein Komprimierungsverfahren.
Hoffe mir kann noch jemand helfen.
LG PAT