Sehr langer String
-
Shade Of Mine schrieb:
str_rec += strDataBuffer;
Was wenn in strDataBuffer eine 0 vorkommt?
und recvfrom heisst UDP und UDP garantiert dir die Uebertragung nicht...
Dann ist die 0 aber ein char. Und die '0' ist sozusagen eine 48 als int. Gibt also daher eig. keine Probleme.
-
SoM meint der char-Wert 0.
-
Was passiert den in diesem Fall? Wäre dies dann die Nullterminierung, so dass ich die nachfolgenden Zeichen vergessen kann (da operator += bis \0 durchläuft)?
Anscheinend hatte ich bisher mit meinen Dateien soviel Glück, dass mir dieser Fall nicht untergekommen ist.
-
build schrieb:
Was passiert den in diesem Fall? Wäre dies dann die Nullterminierung, so dass ich die nachfolgenden Zeichen vergessen kann (da operator += bis \0 durchläuft)?
Ja.
deshalb:
str_rec.append(strDataBuffer, bytes_rec);wobei es natuerlich besser waere das ganze ohne kopieren zu machen.
Und nebenbei bemerkt: du checkst nicht auf Fehler beim recvfrom.
-
build schrieb:
Was passiert den in diesem Fall? Wäre dies dann die Nullterminierung, so dass ich die nachfolgenden Zeichen vergessen kann (da operator += bis \0 durchläuft)?
Ja. Bzw: Ich glaube, es gibt gar keinen operator += (char const*), sondern nur einen operator += (string), bei dem die implizite Konvertierung über den Konvertierungs-Ctor greift. Aber für den Code ist das letztendlich egal.
-
Kellerautomat schrieb:
Ich glaube, es gibt gar keinen operator += (char const*)
doch.
das ist std::string.
da gibts alles.in manchen Implementierungen gibts auch eine koche_kaffee() Funktion.
-
Ich bin jetzt soweit:
#define MAX_PACKET_SIZE 1024 . . . char strDataBuffer[MAX_PACKET_SIZE]; // Unsere Daten // Alle Pakete empfangen size_t bytes_rec = 0; size_t bytes_recv_total = 0; std::string str_rec; std::list<std::string> str_list; do { memset(strDataBuffer, 0, MAX_PACKET_SIZE); bytes_rec = recvfrom(_sock, strDataBuffer, MAX_PACKET_SIZE, 0, 0, 0); // Alles gut gelaufen? if(bytes_rec == SOCKET_ERROR) return; // Na toll, ein Fehler str_rec.append(strDataBuffer); // Bei zuvielen Zeichen, den aktuellen String in eine Liste einfuegen // Danach leeren if(str_rec.length() >= str_rec.max_size()-MAX_PACKET_SIZE) { str_list.push_back(str_rec); // Hinten anfügen str_rec.clear(); } bytes_recv_total += bytes_rec; } while(bytes_rec != 0);Jetzt bin ich soweit, dass ich aus diesen vielen Teilstrings einen großen CString erstellen möchte.
Deshalb würde dieser Ansatz gehen?char *buffer = new char[bytes_rec]; // Ausgabepuffer memset(buffer, 0, bytes_rec); for(std::list<std::string>::const_iterator it = str_list.begin(); it != str_list.end(); it++) { sprintf(buffer, "%s%s", buffer, it->c_str()); }
-
str_rec.append(strDataBuffer);
da hast du immernoch das selbe Problem.
-
Habs jetzt so gelöst und es funktioniert zumindest teilweise:
for(int i = 0; i < MAX_PACKET_SIZE; i++) str_rec += strDataBuffer[i];Bei Textdateien funktioniert dies wunderbar. Bei einem 4MB großen Bild, bekomme ich 1,5KB zuviel. Kann dies immernoch am operator+= liegen?
-
build schrieb:
for(int i = 0; i < MAX_PACKET_SIZE; i++) str_rec += strDataBuffer[i];Ich habe dir die Lösung doch schon gepostet:
str_rec.append(strDataBuffer, bytes_rec);
Bei deiner Schleife hast du nämlich das Problem: was passiert wenn du weniger als MAX_PACKET_SIZE an Daten bekommst? Dann füllst du mit 0 auf. Und das könnte zB deine 1,5k zuviel sein.
-
Oh das habe ich komplett übersehen. Deswegen hier ein verspätetes Danke!
Und was ist in dem Fall, wie du beschrieben hast, dass die Datei den char-Wert 0 enthält? Den meine Dateien sind zwar gleich groß, haben aber die md5 Summen stimmen nicht überein.
-
build schrieb:
Oh das habe ich komplett übersehen. Deswegen hier ein verspätetes Danke!
Und was ist in dem Fall, wie du beschrieben hast, dass die Datei den char-Wert 0 enthält? Den meine Dateien sind zwar gleich groß, haben aber die md5 Summen stimmen nicht überein.std::string kann 0 werte enthalten. Die Frage ist, wie du die Daten dann in die Datei schreibst.
Kommen denn die richtigen Anzahl Bytes jetzt an?
-
Ja die angekommenen Byte passen mit den gesendeten (und der Originaldatei) überein.
Das Reinschreiben übernimmt die fstream.// pb.pData->data sind die durch recv erhaltenen Daten // pb.pData->nlength sind die durch recv erhaltenen Anzahl an Bytes des Datensatzes std::fstream file(filename, std::ios::out | std::ios::binary); file.write(pb.pData->data, pb.pData->nlength); file.close();
-
Und wie bekommst du pData->data?
Da muss ja wieder irgendwo was kopiert werden.Hast du auch die Dateien korrekt als binary geöffnet und nicht als Text?
-
Datei öffnen:
/** Unsere eigentlichen Daten */ struct PacketTransmission { char *data; // Daten an sich size_t nlength; // Dateigroeße }; FILE *fp = fopen(pb.filename.c_str(), "rb"); // Dateigroese herausbekommen fseek(fp, 0, SEEK_END); int length = ftell(fp); rewind(fp); if(pb.pData == NULL) pb.pData = new PacketTransmission; pb.pData->nlength = length; pb.pData->data = new char[length]; fread(pb.pData->data, length, 1, fp); fclose(fp);Setzen eines Strings
void Packet::SetString(std::string strData) { if(pb.pData == NULL) { pb.pData = new PacketTransmission; pb.pData->data = NULL; } if(pb.pData->data == NULL) { pb.pData->data = new char[strData.length()]; pb.pData->nlength = strData.length(); strcpy(pb.pData->data, strData.c_str()); } else { delete pb.pData->data; pb.pData->data = new char[strData.length()]; pb.pData->nlength = strData.length(); strcpy(pb.pData->data, strData.c_str()); } }Kann es sein, dass es daran liegt, dass ich nur ein send hab, welches mehrere MB rüberschickt und dadurch Unmengen an Fehler entstehen können?
-
strcpy(pb.pData->data, strData.c_str());
hier hast du wieder das Problem mit den 0 Bytes.
du brauchst hier memcpyDas Problem ist, du hast keinen echten C String. Ein C String ist nämlich dadurch definiert, dass er mit einem 0 Byte beendet wird. Wenn du binärdaten überträgst ist das aber nicht gegeben und du musst immer die größe mitangeben.
Warum mischst du C und C++ eigentlich so?
PS:
delete pb.pData->data;
das muss
delete [] pb.pData->data;
lauten.
-
Shade Of Mine schrieb:
strcpy(pb.pData->data, strData.c_str());
hier hast du wieder das Problem mit den 0 Bytes.
du brauchst hier memcpyDas Problem ist, du hast keinen echten C String. Ein C String ist nämlich dadurch definiert, dass er mit einem 0 Byte beendet wird. Wenn du binärdaten überträgst ist das aber nicht gegeben und du musst immer die größe mitangeben.
Warum mischst du C und C++ eigentlich so?
PS:
delete pb.pData->data;
das muss
delete [] pb.pData->data;
lauten.Ah nochmal ein sehr sehr großes Danke! Endlich funktioniert es!
Das Vermischen ist eig. im Nachhinein enstanden, da ich anfangs nur C++ genutzt habe und testen wollte, ob es evtl. am fstream / string lag.MD5 stimmt jetzt auch komplett überein.
Nochmal ein großer Dank an alle!