Dateiinhalt in String schreiben, String-Inhalt in Datei schreiben; im gesamtem Wertebereich
-
Hallo zusammen
Meine rudimentären Kenntnisse in der stream-Programmierung lassen mich an meinem aktuellen Projekt scheitern: Ich möchte eine beliebige Datei auslesen und häppchenweise per Netzwerk übertragen und am anderem Ende wieder zusammensetzen.
Die beiden dazu erstellten Programme (Sender und Empfänger) funktionieren grundlegend schon, nur verschlucken sich die Programme, oder besser gesagt die stream-Funktionen fgetc() und fputc(), an den in Dateien doch immer mal wieder vorkommenden Nullbytes.
Zur Fehlersuche habe ich genau definierte Testdatei übertragen lassen und das Ergebnis verglichen. Immer die Bytes mit dem Wert "0" (und "1"...) werden nicht übertragen...
Mal etwas Beispielcode:
__________ Sendeseite
// Deklaration FILE *lesen; char SendPacket[TELEGRAM_LEN + 28]; // main() // [...] // innerhalb einer Schleife: memset( SendPacket, 0, sizeof(SendPacket) ); // fuellt den SendPacket-String mit Nullen for( int i=0; i<TELEGRAM_LEN; i++ ){ SendPacket[19+i] = fgetc(lesen); // Nutzdaten aus Datei in String schreiben } sendto( SendSocket, SendPacket, sizeof(SendPacket), 0, (SOCKADDR *) &SendAddr, sizeof(SendAddr) );
__________ Empfangsseite
// Deklaration FILE *schreiben; char RecvPacket[TELEGRAM_LEN + 28]; // main() // [...] // innerhalb einer Schleife: memset( RecvPacket, 0, sizeof(RecvPacket) ); // fuellt den RecvPacket-String mit Nullen recvfrom( RecvSocket, RecvPacket, sizeof( RecvPacket ), 0,(SOCKADDR*)&RecvAddr, &RecvAddrLen ); for( int i=0; i<TELEGRAM_LEN; i++ ){ fputc( RecvPacket[19+i] , schreiben ); // Nutzdaten des empfangden Telegramms in Datei schreiben }
Wie bereits geschrieben, die Programme funktionieren eigentlich, es kommt die korrekte Byteanzahl am anderem Ende an, die ganzen "Handshakes" zwischen den beiden Programmen funktionieren ... nur wenn die ursprüngliche Datei eine "0" an der entsprechenden Stelle hat, kommt am anderem Ende Mist raus; vor und hinter der eigentlichen "0" ist wieder alles OK...
Die Lösung ist bestimmt einfach: Welche Funktionen aus der stream-Programmierung sollte/muss man verwenden, wenn man die Information aus einem stream 1zu1 in einen String schreiben will (und umgekehrt) ?
Mit fgetc() und fputc(), behaupte ich mal als N00b, geht's nicht; zumindest wie ich diese Funktionen händele...
Bin für jeden Vorschlag und Ratschlag dankbar
MfG André
-
Hast du irgendwo noch Stringfunktionen.
So wie strlen, strcpy oder strcat?Öffnest du die Dateien auch im binary modus?
-
Hallo
den Stream öffne ich mit:
FILE *lesen; lesen = fopen( Dateiname, "rb" );
bzw schreibe ihn mit :
FILE *schreiben; schreiben = fopen( Dateiname_Eingabe, "wb" );
Andere String-Funktionen sind natürlich vorhanden:
Hier Quellcode des Sende-Programms. Es wird ein Telegramm zusammengesetzt welches dann gesendet wird;
das Telegramm enthält neben den Datei-Daten auch eine Teilnehmerkennung (noch k.A. wofür), ein Steuerkommando, eine Telegrammkennung und eine rudimentäre Prüfziffer...
memset( SendPacket, 0, sizeof(SendPacket) ); // fuellt den SendPacket-String mit Nullen sprintf( SendPacket,RecvClientIDsave); // Teilnehmerkennung (2-stellig) strcat( SendPacket,"\xB0" ); // Trennzeichen (1-stellig) strcat( SendPacket,"!DATA!" ); // Kommando (6-stellig) strcat( SendPacket,"\xB0" ); // Trennzeichen (1-stellig) sprintf( SendPacket,"%s%08ld",SendPacket,TelegrammNummer); // Telegrammnummer (8-stellig) strcat( SendPacket,"\xB0" ); // Trennzeichen (1-stellig) for( int i=0; i<TELEGRAM_LEN; i++ ){ SendPacket[19+i] = fgetc(lesen); // Nutzdaten (TELEGRAM_LEN-lang) } strcat( SendPacket,"\xB0" ); // Trennzeichen (1-stellig) SendPacket[20+TELEGRAM_LEN] = SendPacket[ 1]; // Prüfziffer (8-stellig) SendPacket[21+TELEGRAM_LEN] = SendPacket[ 4]; SendPacket[22+TELEGRAM_LEN] = SendPacket[ 7]; SendPacket[23+TELEGRAM_LEN] = SendPacket[ 11]; SendPacket[24+TELEGRAM_LEN] = SendPacket[ 16]; SendPacket[25+TELEGRAM_LEN] = SendPacket[ 19]; SendPacket[26+TELEGRAM_LEN] = SendPacket[(36+TELEGRAM_LEN)/2]; SendPacket[27+TELEGRAM_LEN] = SendPacket[ 18+TELEGRAM_LEN]; sendto( SendSocket,SendPacket,sizeof(SendPacket),0,(SOCKADDR *) &SendAddr,sizeof(SendAddr));
*Das Telegramme enthält viele Trennzeichen und im Klartext-lesbare Zusatzinformationen, die ich zur Fehlersuche benutzt habe/ nutzen wollte, wenn die Kommunikation zwischen den beiden Programmen irgendwie klemmt. Ich hätte dann die Telegramme im Netzwerk mitgeschnitten...
Übrigens weiß ich, dass das zusammensetzen des Telegrammes nicht besonders schön gelöst ist. Hier sehe ich noch etwas Optimierungsbedarf...*
Hier die entscheidenden Zeilen des Quellcodes des Empfangsprogramms:
memset( RecvPacket, 0, sizeof(RecvPacket) ); // fuellt den RecvPacket-String mit Nullen recvfrom(RecvSocket,RecvPacket,sizeof(RecvPacket),0,(SOCKADDR*)&RecvAddr,&RecvAddrLen); // Empfangende Daten verarbeiten for( int i=0; i<TELEGRAM_LEN; i++ ){ fputc( RecvPacket[19+i] , schreiben ); // Nutzdaten des empfangden Telegramms in Datei schreiben }
Gruß André