Datei lesen und versenden
-
Hallo,
ich versuche den Inhalt einer Datei in einen Buffer zu schreiben:
int length; char * buffer2; ifstream is; is.open (fileToSend.c_str(), ios::binary ); // get length of file: length = getFileSize(fileToSend); // allocate memory: buffer2 = new char [length]; // read data as a block: is.read (buffer2 ,length); is.close(); cout << "will send this buffer : " << endl; cout << buffer2; cout <<endl;//returns filesize int getFileSize(std::string fileName) { int result = 0; ifstream is; is.open (fileName.c_str(), ios::binary ); // get length of file: is.seekg (0, ios::end); result = is.tellg(); is.close(); return result; }In der Datei, die gelesen wird steht:
123 ffff gggg XXXDer eingelesene Buffer beinhaltet jedoch:
will send this buffer : 123 ffff gggg XXX²²²²½½½½½½½½¯■¯■¯■Woher kommen diese Sonderzeichen nach den letzten XXX? Ich vermute, dass die Länge der Datei falsch ermittelt wird, oder?
-
1. Warum öffnest Du die Datei zweimal? Es ist unsinnig die Ermittling der Dateigröße durch ein zweites öffnen zu ermitteln.
2. Du kannst doch nicht davon ausgehen, dass Dein Stresm den Du liest mit einem 0 Zeichen terminiert wird. Du bekommst Die Anzahl von Zeichen die Du lesen wolltest. Danach steht nunmal Garbage in Deinem Puffer.
Workarround könnte sein: length+1 allokieren und auf length in den Array 0 eintragen.
-
Hallo,
danke - so klappt es.
Es gibt aber ein weiteres Problem:Es funktioniert bei allen Dateien, die anscheinend keine Sonderzeichen beinhalten.
Sobald ich versuche zb eine .jpg einzulesen, werden nur ein paar Zeichen gelesen:
will send this buffer : Ï ÓHier nochmal zur Sicherheit der Lese-Block:
ifstream is; is.open (fileToSend.c_str(), ios::binary ); // get length of file: length = getFileSize(fileToSend); // allocate memory: buffer2 = new char [length+1]; // read data as a block: is.read (buffer2 ,length); is.close(); buffer2[length] = '\0'; cout << "will send this buffer : " << endl; cout << buffer2; cout <<endl;Was istn da los

Grüße
Alex
-
Warscheinlich nix, nur das die Ausgabe beim ersten 0 abgebrochen wird, Strings werden immer mit 0 terminiert, also auch die Ausgabe. Wobei ich bei der Sache net versteh was das mit MFC zu tun hat (anders gesagt falsches Subforum). Aber das nur nebenbei, aber du kannst keine Binärdatei wie ein Bild einfach so als text Ausgeben.
Gruß Matthias
-
Hi,
das Problem besteht aber auch auf der Empfängerseite - den buffer verschicke ich so über ein Socket und schreibe den Inhalt wieder in eine Datei. Dort landen aber auch nur die paar Zeichen, die in der Ausgabe zu sehen sind.
Sorry wegen dem Forum, wo gehört´s denn hin und kann ein Mod vielleicht verschieben?
Gruß
Alex
-
Dir muss klar sein, dass viele Operationen wie zum Beispiel "cout <<" für einen char* eben auf ein 0 Zeichen reagiert...
Wenn Du binär in die Datei schreiben willst solltest Du auch entsprechend eine Funktion wie write verwenden, bei der Du die Länger der zu schreibenden Daten angibst!
BTW Nochmal:
Dein Funktion getFileSize ist Schotter. Warum öffnest Du eine Datei nochmal um die Größe zu ermitteln, wenn Du sie schon offen hast?
-
Dieser Thread wurde von Moderator/in Martin Richter aus dem Forum MFC (Visual C++) in das Forum C++ verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Hallo,
jap, das mit getFileSize ist mir klar, ist korrigiert.
Das Schreiben funktioniert nun per:f.write(buffer, nret);Nun gibt es aber ein anderes Problem - evtl sollte ich dafür einen neuen Thread aufmachen, ich versuche es aber erstmal hier, um nicht alles voll zu posten.
Das Versenden kleinerer Dateien funktioniert (160 byte).
Versuche ich eine größere (80 kByte) Datei zu versenden, beinhaltet die Empfangsseite ab einem bestimmten Punkt im Buffer nur noch Schrott.Ich habe probehalber den Buffer vor dem Versenden in eine Datei geschrieben - da passt es noch. Ergo geht beim Senden was schief.
Hängt es mit meiner Vorgehensweise ab? Der Algorithmus ist im moment so:
1. Datei lesen und Größe feststellen
2. Sender versendet Header mit Dateinamen und Größe.
3. Empfänger richtet Buffer entsprechend der Dateigröße ein und sendet ein ACK
4. Sender empfängt ACK und sendet den gesamten Buffer auf einmal.Jetzt kann man nicht beliebig große Datenpackete versenden, der Buffer wird von irgendeiner Schicht segmentiert und da vermute ich den Fehler. Sieht das jemand ähnlich?
In diesem Fall müsste ich den Buffer in N Pakete zerlegen und häppchenweise senden.
-
filth schrieb:
ich versuche den Inhalt einer Datei in einen Buffer zu schreiben:
einfach so:
std::ifstream is( fileToSend.c_str(), std::ios_base::binary ); std::string buffer( (std::istreambuf_iterator< char >( is )), std::istreambuf_iterator< char >() ); // erfordert #include <iterator>klappt auch mit Sonderzeichen
Bem.: ich hoffe Du hast nicht MS VC6 - das kann das nicht
-
Hallo Werner,
danke für den Codeschnippsel, aber das Lesen funktioniert schon - siehe mein letztes Posting

Hilfe bzgl des neuen Problems wäre aber erwünscht
-
filth schrieb:
Hilfe bzgl des neuen Problems wäre aber erwünscht

Der C++-Weg so etwas zu lösen, besteht darin, sich einen passenden std::streambuf zu schreiben. Diesem kann man dann die Aufgabe überlassen, die Pakete zurechtzuschneiden und zu verschicken. Das sähe in etwa so aus:
#include <streambuf> #include <iostream> #include <fstream> #include <vector> #include <string> #include <cassert> class Packager : public std::streambuf { public: explicit Packager( std::size_t n ) : m_buffer( n ) { // Schreibpuffer auf den 'm_buffer' setzen setp( &m_buffer[0], &m_buffer[0] + m_buffer.size() ); } protected: virtual int_type overflow( int_type m = traits_type::eof() ) { assert( !m_buffer.empty() ); assert( pbase() != 0 && pptr() > pbase() ); if( !write( pbase(), std::size_t( pptr() - pbase() ) ) ) return traits_type::eof(); // Fehler beim Schreiben setp( &m_buffer[0], &m_buffer[0] + 1, &m_buffer[0] + m_buffer.size() ); m_buffer[0] = traits_type::to_char_type( m ); return traits_type::not_eof( m ); } virtual int sync() { assert( !m_buffer.empty() ); assert( pbase() != 0 && pptr() >= pbase() ); if( pptr() > pbase() ) { if( !write( pbase(), std::size_t( pptr() - pbase() ) ) ) return -1; // Fehler setp( &m_buffer[0], &m_buffer[0] + m_buffer.size() ); } return 0; // ok } private: bool write( const char* buf, std::size_t buf_len ) { // hier kannst Du jetzt Deine Daten absenden // buf_len ist immer <= N (s. Konstruktor) return true; // ok } std::vector< char > m_buffer; };in der Methode write musst Du dann den Code einfügen, der die Daten versendet.
Vorteil des streambuf's liegt in der Kombination mit dem ostream, d.h. man kann unmittelbar Objekte reinschreiben. Die Anwendung sähe in Deinem Fall so ähnlich aus wie:
int main() { using namespace std; Packager packager( 60 ); // Paketgröße wählen ostream out( &packager ); string fileToSend = "input.txt"; out << "Header"; // Datei-Header ifstream is( fileToSend.c_str(), ios_base::binary ); out << is.rdbuf(); // schreibt die (beliebig große) Datei komplett raus if( out.flush() ) // flush ruft sync cout << "alles gesendet" << endl; return 0; }Gruß
Werner@Edit: Bugfix Zeile 12 - Konstante 200 in buffer(..) durch n ersetzt.
-
Ui gleich kompletter Code.
Danker Werner, ich werde es mir morgen in Ruhe anschauen und ausprobieren!
Grüße
Alex