Benutzung von setvbuf?



  • Ich möchte abdruckbare und nicht abdruckbare Zeichen (binär) in eine Datei mit fwrite schreiben. Das klappt soweit auch ganz gut. Das Problem ist die schlechte Performance. Da jedes Zeichen einzeln geschrieben wird, ist der Schreibvorgang 80 % der Elapsed-Time des Programms. Ich wollte mit setvbuf und _IOFBF 4096 Blöcke jeweils puffern. Und anschließend mit fflush(stream) die Daten rausschreiben an den Stream. Leider schreibt er mir jedesmal mit fwrite schon in den stream output. Irgendwie funktioniert setvbuf nicht. Muss ich fwrite ersetzen? ABer wie bekomme ich die Daten in den Stream? Vielleicht habe ich nicht verstanden, wie setvbuf funktioniert.



  • Sammle deinen gesamten zu schreibenden Dateiinhalt zuvor in einem Speicherbereich und benutze 1x fwrite (blocknum = 1) mit anschließendem fclose.



  • Das habe ich auch versucht. Aber wie speicher ich meine "binären" Hashcodes? Ich benutze momentan fwrite(&hash,sizeof(uint16_t),1,fp2)...Ich kann doch nicht sprintf(...%u...) benutzen, weil der binäre Inhalt verloren geht und der Code als Zahl dasteht.



  • Bist heute nicht gut drauf, oder?
    Willst mir jetzt nicht erzählen, dass du C programmierst und nicht weisst, wie man mehrere Werte gleichen Typs hintereinander im Speicher ablegt?
    Hast du schon mal was von Arrays gehört?

    uint16_t ist nur C99,
    also z.B. auch wenn dies inflationär zum Parallelthread ist:

    #define ANZAHLMEINERWERTE 4711
    unsigned short werte[ANZAHLMEINERWERTE];
    werte[0]=1;
    werte[1]=2;
    ...
    if( fwrite(werte,sizeof werte,1,fp) )
      puts("hat geklappt");
    else
      puts("werte konnten nicht geschrieben werden");
    


  • Sorry. Natürlich weiß ich wie das geht. Mein Problem ist dass hintereinander im Ablauf des Programms mal ein Character, dann eine Zahl und wieder ein Binärwert kommen. Ich versuche das in einem gemeinsamen buffer abzulegen, den ich dann entleere.



  • Ich möchte alles in einen Zwischenpuffer (char * oder char[]) schreiben und weiß leider nicht, wie man Binärwerte in einem Textfeld in C abspeichert (sprintf?). Ich will den Buffer blockweise leeren über fwrite. In den Buffer werden Characters, Zahlen oder Binärwerte in beliebiger Reihenfolge geschrieben.



  • Ein Lösungsansatz: memcpy()



  • Lass doch mal das fflush weg. Wenn der Buffer voll ist und beim fclose wird eh geschrieben.
    Oder hast du irgendwo ein eigenes fwrite implementiert?
    Und sei doch Großzügig mit dem Buffer und mach den mal 100k groß.



  • memcpy hört sich gut an. Das werde ich morgen gleich ausprobieren. Das funktioniert - glaube ich - auch bei binären Daten. Ich habe 11 Jahre lang Ansi C auf dem Großrechner programmiert. Dort gab es für alles (I/O usw.) sog. Systemcalls. Daher bin ich nicht mehr mit allen Funktionen in C vertraut. Danke für den tollen Einsatz.



  • Irgendwie funktioniert mein memcpy nicht. Ich habe memcpy(tmp,&hvalue,sizeof(uint16_t)) mit char tmp[100] programmiert und bekomme beim Debuggen \000 für hvalue = 6144 zurückgeliefert. Mache ich was falsch?



  • 6144 = 0x1800, in Little Endian Speicherung könnte es hinkommen, daß das mit 0 beginnt. Schau dir die Ausgabe doch mal etwas ausführlicher an.



  • Ich habe gelesen dass das Alignment der Bits beim memcpy eine Rolle spielt. Ich habe eine Datei mit "wb" binär geöffnet und schreibe einen hashcode (uint16_t) binär mit fwrite in die Datei. Das Gleiche versuche ich mit memcpy zu erreichen, nur dass in einen String geschrieben wird. Geht das überhaupt? Befehle wie strlen, strcpy usw. funktionieren bei binären Daten jedenfalls nicht. Kann ich den gleichen output mit memcpy wie bei fwrite bekommen? Gibt es andere Möglichkeiten, einen binären Wert in einem String zu speichern?



  • Ich habe hvalue = 1565 ausprobiert. In der Ausgabe tmp[2] steht /035 /006.



  • Du hast Recht. Das entspricht 29 dezimal und 6 dezimal für die beiden Bytes des uint16_t Wortes. Es handelt sich um einen Byte-Flip. Liegt wohl daran dass mein x86 Rechner little endian ist. Kann man das korrigieren?



  • memcpy() sieht deine Daten genauso wie fwrite() als reine Byte-Folge, damit sollte es eigentlich auch das selbe in das Ziel schreiben wie fwrite. Aber vermutlich nutzt dein Debugger String-Funktionen, um deinen Zwischenspeicher anzuzeigen und wird deshalb durch die \0-Bytes durcheinandergebracht.


Log in to reply