Dateien bearbeiten



  • Hallo!
    Ich debugge schon seit 2 Stunden und bin immernoch nicht auf di eLoesung meines Problems gekommen. 😞
    Ich habe eine Datei, die ich per std::ifstream einlese und zwar zeilenweise in einen std::vector<std::string>
    Nun bearbeite ich den Vektor zeichenweise, indem ich den Wert des chars um eins erhoehe (++). Dann schreibe ich die Datei per std::ofstream auf den Rechner. Wenn ich diese Datei dann wieder einlese (auch wieder zeilenweise - vielleicht hat das ja damit was zu tun...) und die char-Code wieder abziehe (--) und die Datei dann erneut speichere, muss ich feststellen dass bei einigen Dateien Daten verloren gegangen sind... Aber nicht bei allen - nur bei speziellen Sachen wie JPG-Dateien.
    Uebrigens, lass ich die char-Erhoehung und Vertiefung weg, laeuft alles glatt.
    Der Code ist sehr gross (2000 Zeilen) und durch diverse Klassen gekapselt und da ich nicht wirklich weiss, wo das Problem ist, kann ich auch kein Code-Snippet posten... 😞
    Es handelt sich bei dem ganzen Uebrigens um einen Datei-Verschluessler.

    So sehen die Verschluesselungsfunktionen aus:

    char Cryptor::Encrypt(char s)
    {
    	return s-1;
    }
    
    char Cryptor::Decrypt(char s)
    {
    	return s+1;
    }
    

    Aber wie gesagt, weiss nicht wirklich wo das Problem ist. Bei meinem letzten Datei-Verschluessler (der sehr viel einfacher gestrickt ist) hat alles geklappt, da ich die Datei zeichenweise eingelesen hab und nicht zeilenweise so wie es jetzt der Fall ist. Vielleicht liegt das Problem ja hier (fuer mein Programm MUSS ich die Datei zeilenweise einlesen).
    Hoffe, jemand kann mir helfen. Bin am verzweifeln 🙄

    Gruss
    Cartman



  • Hmm. Wie siehts den mit überläufen aus? Also so, dass das +1 die chars zum überlaufen bringt.



  • drakon schrieb:

    Hmm. Wie siehts den mit überläufen aus? Also so, dass das +1 die chars zum überlaufen bringt.

    Was soll damit sein? Die chars werden halt, wenn sie am maximum sind (0) zu 255 oder -1 (je nachdem ob char signed oder unsigned darstellt) dekrementiert.
    Oder mach ich einen Denkfehler?

    Gruss
    Cartman



  • Ich versteh nicht was dein Problem ist... ich hab auch mal schnell ein getippt, falls es hilft:

    void Decrypt::Checkalphabet(std::string &line, const char *Filename)
    {
    	std::string new_line = line;
    	const char delta = 3;
    
    	std::cout<< (char)16 << "File wird verschl"<<(char)129<<"sselt..."<<std::endl;
    
    	for(int i=0; i < new_line.length(); i++)
    	{
    	 new_line[i] += delta;
    	}
    
    	std::cout<< (char)16 << "File wurde erfolgreich verschl"<<(char)129<<"sselt."<<std::endl;
    
    	ExportFile(new_line, Filename);
    };
    

    EDIT:
    Ist das einfache Verschiebechiffre, sollte klar sein...



  • way schrieb:

    std::cout<< (char)16 << "File wird verschl"<<(char)129<<"sselt..."<<std::endl;

    sinn?



  • Hallo!
    Es verschluesselt auch... nur eben nicht jede Datei - und ich frage mich eben warum:

    ofstream outp;
    	outp.open("C:\\tes.txt", ios::binary|ios::out);
    	if (!outp) return 0;
    	for (size_t i=0; i<256; i++) {
    		outp.write(reinterpret_cast<char*>(&i), 1);
    	}
    

    Die erstellte Datei kann ohne Datenverlust verschluesselt und anschliessend entschluesselt werden... Wies klappt das bei anderen Dateien wie eben z.B. JPG nicht...

    Gruss
    Cartman


  • Administrator

    Ein JPEG solltest du mit ios::binary öffnen. Sobald ein File etwas anderes als Text darstellt, solltest du ios::binary nehmen. Es gibt manchmal Bytecodes, welche das Ende eines Files beschreiben. In einem Textfile mag das sinnvoll sein, in einem binären File allerdings weniger. ios::binary ignoriert einfach alle solchen Codes und gibt dir die Daten wirklich so zurück, wie sie im File sind, ohne sie zu verändern.
    http://www.cplusplus.com/reference/iostream/ios_base/openmode.html

    Grüssli



  • Hallo Dravere!
    Danke, aber ich lese die Datei ja binaer.
    Mir ist aber bei meienm Test (siehe Post ueber dir) was aufgefallen. Die Enddatei ist leicht veraendert von der Originalen Datei, und zwar befindet sich in der entschluesselten Datei noch eine zusaetzliche Leerzeile, dass so bei anderen entschluesselten Dateien nicht vorkommt.
    Der Text laesst sich wegen den Sonderzeichen hier leider nicht kopieren (edit// okay habs geschafft, das erste Zeichen war das Nullzeichen, deswegen gings nich)

     
    
     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
    

    Dies ist die Originaldatei.

     	
    
     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
    

    Und dies die entschluesselte... Jetzt bin ich verwirrt.

    Gruss
    Cartman



  • Eric Cartman schrieb:

    Ich habe eine Datei, die ich per std::ifstream einlese und zwar zeilenweise in einen std::vector<std::string>
    [...]
    Aber nicht bei allen - nur bei speziellen Sachen wie JPG-Dateien.

    Preisfrage: Was bedeutet zeilenweise bei JPG? Was versteht man unter zeilenweise im Sinne der Implementierung von getline?



  • Michael E. schrieb:

    Eric Cartman schrieb:

    Ich habe eine Datei, die ich per std::ifstream einlese und zwar zeilenweise in einen std::vector<std::string>
    [...]
    Aber nicht bei allen - nur bei speziellen Sachen wie JPG-Dateien.

    Preisfrage: Was bedeutet zeilenweise bei JPG? Was versteht man unter zeilenweise im Sinne der Implementierung von getline?

    Bis ein newline-Zeichen ('\n') auftritt.. Bei meiner Test-JPG sind es 107 Zeilen. Willst du mir damit etwas bestimmtes sagen? Sorry, ich hab manchmal ne etwas lange Leitung...

    Gruss
    Cartman



  • Binärdateien haben üblicherweise keine Zeilenumbrüche, sie sind einfach nur hintereinander weggeschrieben, das mal ein Zeilenumbruch stattfindet ist ansich nur Purer Zufall weil zB eine 4Byte Zahl mal ein Byte hat das als Char dem Zeilenumbruch entspricht. Deswegen liest man solche Dateien auch immer binär ein und Blockweise, dh nicht eine Zeile auf einmal sondern einen Datenblock von x Bytes.



  • @Xebov
    Aber sie koennen welche haben. Wenn das nicht der Fall ist, waere das auch kein Problem, dann hatte ich eben einen std::vectorstd::string mit einem Element... Nur wenn die Datei etwas groesser wird koennte das da Probleme geben...

    However, ich konnte mein Problem loesen. Wenn ich eine Datei zeilenweise einlese und verschluessle, muss ich beachten, dass durch die Verschluesselung nicht versehentlich ein newline-Zeichen entsteht, das waer dann bei der weiteren Verarbeitung problematisch...

    char Cryptor::Encrypt(char s)
    {
    	if (s == 9 || s == 12) s+=2;
    	else if (s == 10 || s == 13);
    	else ++s;
    	return s;
    }
    
    char Cryptor::Decrypt(char s)
    {
    	if (s == 11 || s == 14) s-=2;
    	else if (s == 10 || s == 13);
    	else --s;
    	return s;
    }
    

    Zumindest funktioniert es jetzt so mit meienr JPG-Datei und auch mit der Testdatei...
    Danke an euch!

    Gruss
    Cartman


  • Administrator

    @Eric,
    Wie wäre es, wenn du ganz auf die Zeilen verzichtest? Man kann jedes File ohne Probleme über Datenblöcke lesen und beschreiben. Also auch ein Textfile. Dadurch wirst du völlig unabhängig von den "Zeilen".

    Im übrigen noch eine kleine Anmerkung:
    Was bei einem Überlauf oder Unterlauf einer Zahl passiert, ist laut Standard nicht definiert, bzw. dem Kompiler überlassen. Daher Vorsicht bei solchen Sachen. Fang sowas lieber ab und mach das gewünschte Verhalten selber.

    Grüssli



  • Dravere schrieb:

    @Eric,
    Wie wäre es, wenn du ganz auf die Zeilen verzichtest? Man kann jedes File ohne Probleme über Datenblöcke lesen und beschreiben. Also auch ein Textfile. Dadurch wirst du völlig unabhängig von den "Zeilen".

    Womoeglich... Nur habe ich dabei zwei Probleme... 1. Muesste ich saemtliche Klassen neu bauen oder sie wenigstens bearbeiten. 2. versteh ich nicht wirklich wie das einlesen bestimmter Datenbloecke gemeint ist.

    Dravere schrieb:

    Im übrigen noch eine kleine Anmerkung:
    Was bei einem Überlauf oder Unterlauf einer Zahl passiert, ist laut Standard nicht definiert, bzw. dem Kompiler überlassen. Daher Vorsicht bei solchen Sachen. Fang sowas lieber ab und mach das gewünschte Verhalten selber.

    Das wusst ich nicht... Danke fuer den Hinweis. Dann bau ich mir das eben selbst schnell zusammen, sollte kein Problem sein 🙂

    Gruss
    Cartman



  • Klassen nachzubearbeiten soltle kein großes Problem sein.

    Einen Datenblock ist schlicht ein Block aus Daten, du kannst dir zB einen machen der immer genau 200Byte einliest->verändert->rausschreibt, das is alles, dabei gilt es nur das Dateiende richtig zu erfassen und die Manipulation abzusichern, um Escapesequenzen mußt du dir dabei keine Sorgen mehr machen. Im übrigen werden Binärdateien immer so gelesen und beschrieben, ich würde dir empfehlen dich in diesem zusammenhang mal über Chunks zu informieren, dann weist du mal wie solche Binärdateien aufgebaut werden und Funktioneiren.


  • Administrator

    // File öffnen
    std::ifstream input("...", std::ios::binary | std::ios::in);
    std::ofstream output("...", std::ios::binary | std::ios::out);
    
    // Unser Datenblock.
    std::vector<char> data;
    data.resize(4096);
    
    while(input.read(&data[0], data.size())
    {
      // Wieviele Daten wurden gelesen?
      if(data.size() > input.tellg())
      { data.resize(input.tellg()); }
    
      // Bearbeite die Daten.
      edit_data(data);
    
      output.write(&data[0], data.size());
    }
    

    So ist man völlig unabhängig von irgendwelchen Bytecodes. Und das bearbeiten deiner Klassen sollte ja wirklich kein Problem sein. Das nennt sich schliesslich programmieren 🙂

    Grüssli



  • @Dravere
    Dankeschoen. Da werd ich heut wohl noch ne Menge zu tun haben 🙂

    Gruss
    Cartman



  • Dravere schrieb:

    Im übrigen noch eine kleine Anmerkung:
    Was bei einem Überlauf oder Unterlauf einer Zahl passiert, ist laut Standard nicht definiert, bzw. dem Kompiler überlassen. Daher Vorsicht bei solchen Sachen. Fang sowas lieber ab und mach das gewünschte Verhalten selber.

    Nicht ganz, das Verhalten ist nur bei signed -Typen undefiniert.

    C++ Standard 3.9.1 schrieb:

    Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation of that particular size of integer.41)

    ________
    41) This implies that unsigned arithmetic does not overflow because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting unsigned integer type.


  • Administrator

    Nexus schrieb:

    Nicht ganz, das Verhalten ist nur bei signed -Typen undefiniert.

    Er benutzt ja auch ein char . Wobei du natürlich recht hast. Und mir gerade auffällt, dass ich einen Denkfehler gemacht habe, ein char kann ja theoretisch auch unsigned sein. Ein Standard voller Ausnahmen 🙂

    Grüssli


Anmelden zum Antworten