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 gespeichert

    Wä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.




  • Mod

    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


  • Mod

    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 1001

    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 1001

    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 1001

    Und der Komprimierungsalgorithmus ist (z.B.):

    a = 0100 0110 1001
    b = 1110 0101 0111

    Dann 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


  • Mod

    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^^


  • Administrator

    Du liest aus dem File eine Anzahl an char . Ein char 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 du char 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


  • Mod

    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.


  • Administrator

    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 Antwort 😃

    Grü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.



  • @SeppJ:

    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
    

    😉



  • @TyRoXx:

    [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


Anmelden zum Antworten