FileStream und binary mode



  • hi!

    Ich wollte meine Daten im binärmodus speicher...
    leider komm ich grad net so sehr zurecht damit..

    ich hab ein tut gefunden:
    http://209.85.129.104/search?q=cache:lQsrYRnCTWgJ:www.fachinformatiker-ihk.de/download/extras/Fh_mit_BCB.pdf+c%2B%2B+borland+binary+schreiben&hl=de&ct=clnk&cd=1&gl=de
    Seite 6.
    Ich hab mir also eine Strucktur geschrieben die meine Daten enthalten soll...

    hab es auch wchar_t gemacht, oder geht auch String???

    ich hab Probleme beim umwandeln:
    Ich habe einige Daten im String format vorliegen. wie bekomme ich das in WideChar umgewandelt ohne das mir was vom inhalt verloren geht?
    der String kann so lang sein wie der user möchte.
    Zudem muss ich das ganze dann wieder rückwandeln können wenn ich es einlese, also von wchar_t zu String...
    wie mach ich das am besten?

    Danke schonamal für die Hilfe 😃



  • Ich habs jetzt so gemacht:

    struct TMeineDaten
    {
      wchar_t Zusatz;
      wchar_t Name;
      wchar_t Vorname;
      wchar_t Bemerkung;
    }
    

    und im code wo ich dann jede eingetragene zeile speichere:

    String Zusatz="Test";
    fstream outStream(Pfad.c_str(),ios::binary|ios::out);
    for(int i=0;i<Datenanzahl;i++)
    {
       TMeineDaten Daten;
       int l;
       l = Zusatz.WideCharBufSize();
       Zusatz.WideChar(Daten.Zusatz,l);
       l = EditUsername->Text.WideCharBufSize();
       EditUsername->Text.WideChar(Daten.Name,l);
    
    usw...
    

    da kommt der fehler:

    Cannot convert 'int' to 'wchar_t *'
    Type mismath in parameter 'dest'(want 'wchar_t *',got 'wchar_t')
    

    Was is da falsch?? :<

    hier würde ich dann jede zeile in der schleife schreiben:

    outStream.write((char*)&Daten,sizeof(TMeineDaten));
    

    Warum kommt aber obens chon der fehler?? -.-



  • Ein wchar_t enthält nur ein einzelnes Zeichen. Du bräuchtest hier schon ein Array (natürlich initialisiert).
    Warum willst du eigentlich WideChars verwenden? Außerdem gibt es ja noch WideString.



  • Er will einen AnsiString binärsicher schreiben und wieder einlesen, geht um den mit blowfish verschlüsselte binäre AnsiString.
    @Puccini
    Das Schreiben war schon O.K. so, wenn ich das richtig sehe. Problem war das Einlesen eines binären Stringes mit getline, wenn dort zufällig ein std::endl in dem verschlüsselten String auftaucht.



  • witte schrieb:

    Er will einen AnsiString binärsicher schreiben und wieder einlesen, geht um den mit blowfish verschlüsselte binäre AnsiString.

    Auch dafür macht wchar_t keinen Sinn. unsigned char reicht völlig aus.



  • Braunstein schrieb:

    Auch dafür macht wchar_t keinen Sinn. unsigned char reicht völlig aus.

    Hat ja auch kein Mensch behauptet, dass er wchar_t nehmen soll. Er soll sich um das Einlesen kümmern.



  • hi,

    ich hab das jetzt nochmals umgeschrieben, da widechar wirkich quatsch war XD

    Jetzt hab ichs so:

    Schreiben:

    String Username = EditUsername->Text.c_str();
    int Lang = Username.Length();
    outStream.write((const char*)&Lang,sizeof(Lang));
    char *buffer = new char(Lang);
    buffer=NULL;
    buffer = Username.c_str();
    outStream.write((const char*)&buffer,Lang);
    

    Lesen:

    String Username;
    int Lang;
    char *buffer;
    inStream.read((char*)&Lang,sizeof(Lang));
    buffer=new char(Lang);
    buffer=NULL;
    inStream.read((char*)&buffer,Lang);
    Username=buffer;
    

    Funktioniert nicht so richtig.. warum?? :<
    ich lass mir den String dann noch ausgeben, und da ist er das erste mal leer und wenn ich nochmal auf den Button laden drücke, steht auf einmal was drin -.-

    gibts noch einen besseren weg?
    Ich will auch die integerwerte der buchstaben speichern, doch die tauchen dann in der datei wieder als buchtaben auf!

    Symbol=int(Username[k]);
    outStream.write((const char*)&Symbol,sizeof(Symbol));
    

    damit sollen die Usernamen nicht im klartext in der datei stehen, sondern halt als integerwerte XD.

    liegt das am const char und char??



  • Schau Dir mal als "Referenz" diesen Code an:

    void __fastcall TForm1::btnEncryptClick(TObject *Sender)
    {
    
        String msg = "test";
        String key = "test";
    
        TBlowfish b1((unsigned char *)key.c_str(), key.Length());
        b1.Encrypt(&msg);
    
        fstream ofs("C:\\temp\\msg.dat", ios::binary | ios::out);
        ofs << msg.Length() << msg;
    
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::btnDecryptClick(TObject *Sender)
    {
    
        String key = "test";
        int Length;
    
        fstream ifs("C:\\temp\\msg.dat", ios::binary | ios::in);
        ifs >> Length;
    
        unsigned char *buffer = new unsigned char[Length];
        ifs.read(buffer, Length);
    
        TBlowfish b1((unsigned char *)key.c_str(), key.Length());
        String msg = (char*)buffer;
        delete[] buffer;
    
        b1.Decrypt(msg);
    
    }
    //---------------------------------------------------------------------------
    

    Fang von dort an und pass es Dir an. Da fehlt aber noch die Fehlerbehandlung und es sollte sichergestellt sein dass das delete[] immer aufgerufen wird.



  • der meckert mich an das "AnsiString" nicht implementiert ist für den operator << im typ ostream...

    bei der zeile:
    outStream<<msg.Length()<<msg;

    kann ich da einfach schreiben:
    outStream<<msg.Length()<<msg.c_str();
    oder wird dabei der Blowfish-string zerstört??



  • Setz das Symbol VCL_IOSTREAM in Projekt=>Optionen=>Verzeichnisse/Bedingungen=>Bedingungen=>Definition



  • ich hab ein Problem...

    Ich hab nen String:
    msg=100ABCDEF
    als beispiel..
    wenn ich dann schreibe:

    outStream<<msg.Length()<<msg;
    

    und mir die länge ausgeben lasse mit ShowMessage(msg.Length());
    dann steht da 9, wies sein sollte.
    diese Zahl steht auch in der Datei.
    Da steht:
    9100ABCDEF

    Wenn ich die datei jetzt auslese mit:
    inStream>>Lang;
    ist Lang auf einmal 9100
    warum das -.-
    ich dachte wenn ich binär speicher wäre das nicht der fall... ich dachte da sieht man die zahlen nicht in der datei. :<
    wie muss ich das nun machen ?
    -.- bin zu doof für sowas 😡



  • Hallo

    Was erwartest du? Du must einlesen wie du gespeicherst hast. Also erstmal die Länge der Zeichenkette, dann die Zeichenkette selber. Da hast du nun aber ein Problem : Die Länge der Zeichenkette speicherst du nicht binär, was zur Folge hat das diese in der Datei eine variable Länge hat und nicht mehr von der eigentlichen Zeichenkette getrennt werden kann.

    Korrekt sollte es zum Beispiel so aussehen :

    // speichern
    AnsiString msg = "...";
    unsigned int length = msg.Length();
    outStream << reinterpret_cast<const char*>(length); // Der Wert in length wird in genau 4 Bytes gespeichert
    outStream << msg.c_str(); // Die Zeichenkette wird gespeichert
    
    // einlesen
    unsigned int length;
    char* buffer = new char[length +4];
    inStream.read(4, buffer; // Es werden genau 4 Byte ausgelesen
    length = reinterpret_cast<unsigned int>(*buffer); // Umwandlung in korrekten Integer
    delete buffer;
    buffer = new char[length +1]; // Zwischenspeicher zum Einlesen
    inStream.read(length, buffer);
    buffer[length] = 0;
    AnsiString msg = buffer;
    delete buffer;
    

    bis bald
    akari

    /Edit : Code korrigiert



  • ich bekommen immer einen access violation fehler wenn ich versuche meine datei zu speichern:

    String Pfad= Form1->Pfad.c_str();
    			Form1->lastPfad=Pfad;
    			Form1->aktiverPfad->Caption=Form1->lastPfad;
    	fstream outStream(Pfad.c_str(),ios::binary|ios::out);
    		try{
    						String key = EditPasswort->Text;
    						TBlowfish c1((unsigned char *)key.c_str(), key.Length());
    						String MD5Key = getMD5(key);
    						unsigned int ULang;
    						ULang=MD5Key.Length();
    						outStream<<reinterpret_cast<const char*>(ULang);
    							ShowMessage(ULang);
    						outStream<<MD5Key.c_str();
    

    ShowMessage wir schon nicht mehr angezeigt, da beim schreiben des integers ein fehler auftritt......



  • Hallo

    Ah noch ein Fehler in meinem Code...
    Das speichern der Längenangabe muß natürlich auch byteweise und nicht mit Stream-Operator passieren

    outStream.write(4, reinterpret_cast<const char*>(ULang));
    

    bis bald
    akari



  • also so hier??

    outStream.write(reinterpret_cast<const char*>(ULang),4);
    outStream<<msg.c_str();
    

    oder so:

    outStream.write(reinterpret_cast<const char*>(ULang),4);
    outStream.write(msg.c_str(),ULang);
    

    Ibeiden fällen bleibt die Datei 0 Byte gross, also wird nix geschrieben!
    -.-
    wo is den da schon wieder der fehler :<
    ich geh hier nochmal fest. is es wirklich so schwer binär in eine datei zu speichern? :<

    edit:

    outStream.write(reinterpret_cast<const char*>(&ULang),4);			outStream.write(MD5Key.c_str(),ULang);
    

    So wird was in die Datei geschrieben!

    String UN= Form1->EditUsername[i]->Text.c_str();
    ULang=UN.Length();
    outStream.write(reinterpret_cast<const char*>(&ULang),4);
    for(int k=0;k<ULang;k++)
    {
    Symbol=int(UN[k+1]);
    outStream.write(reinterpret_cast<const char*>(&Symbol),4);
    }
    

    warum wird hier nicht die Zahl sonder wieder der buchstabe in die Datei geschrieben?ß :<
    ich will ja grade dasman nicht den text lesen kann -.-

    ich hab hier noch was gefunden 😃
    würde das gehen? oder wegen den ganzen sonderzeichem im blowfish auch net?? :<
    http://www.bytesandmore.de/rad/index.htm?http://www.bytesandmore.de/rad/cpp/snipp/sc01007.php



  • akari, du kennst dich doch damit supi aus odr?? 😃

    könnte ich dir mal ein Projekt schicken und du schaust dir das mal an warum das net funktioniert?? :>

    ich bin hier am verzeifeln.. nichts, kein einzieges tut hilft mir -.-
    also muss ich mich ja irgendwie doof anstellen, wenns bei anderen geht :<



  • Hallo

    Also nochmal zusammengefasst und getestet

    // Speichern
    AnsiString test = "Das ist ein Test";
    unsigned int length = test.Length();
    ofstream of("test.dat", ios::binary|ios::out);
    of.write(reinterpret_cast<char*>(&length), 4); // Hier hat noch der &-Operator gefehlt
    of.write(test.c_str(), length);
    
    // Laden
    char* buffer = new char[4];
    ifstream of("test.dat", ios::binary|ios::in);
    of.read(buffer, 4);
    int length = *(reinterpret_cast<int*>(buffer)); // Hier muß in Pointer gecastet werden
    delete[] buffer;
    buffer = new char[length +1];
    of.read(buffer, length);
    buffer[length] = 0;
    AnsiString test = buffer;
    delete[] buffer;
    

    warum wird hier nicht die Zahl sonder wieder der buchstabe in die Datei geschrieben?

    Natürlich werden Zahlen in die Dateien geschrieben, Computer arbeiten intern ausschließlich mit Zahlen. Die Datei besteht aus den ASCII-Codes der Zeichen. Wenn du die Datei in einem Editor ausmachst interpretiert dieser natürlich die Zahlen wieder als Zeichen. Das ist trotzdem korrektes binäres Speichern von Zeichenketten. Wenn du die Zeichenkette ganz unlesbar machen willst must du sie verschlüsseln.

    bis bald
    akari



  • oh man, jetzt gehts 😃

    danke dir nochmals 1000mal für die hilfe 😃
    ich hoffe das jett wirklich keine fehler mehr kommen -.-..

    aber das war jetzt ne harte nuss XD
    hoffe es hilft auch anderen weiter, was du hier an arbeit geleistet hast 😉



  • Da ist immer noch ein Fehler drin.
    Puccini, ist das der mit Blowfish verschlüsselte String, den Du wieder einlesen willst? Dann wird Zeile 17 nicht laufen, wenn zufällig ein '\0' in dem String steht.

    AnsiString msg = AnsiString(buffer, Length);
    


  • genau der is es..

    also muss ich zeile 17 mit deiner austauschen, dann gehts??


Log in to reply