Große Datei kopieren
-
cooky451 schrieb:
Wenn ich jedoch dann z.b. in 100er oder 1000er Blöcken lese dann kommt da am Ende nur Müll raus.
Nö, wie kommst du denn auf die Idee?
test.txt Datei Inhalt:
abcdefghijklmnopqrstuvwxyz123456790file.read( &FileData[0], 100 ); f.write( &FileData[0], 100);dbg.txt Datei Inhalt:
abcdefghijklmnopqrstuvwxyz123456790 September November December %H:%M:%S

Ich versuchs gleich mal mit deinem Code ansonsten werde ich wohl doch mal in die WIN API schauen.
-
@ cooky451
Das funktioniert auch nicht das Problem was ich jetzt hab hatte ich vorhin auch schonmal.^^
std::vector<char> buf(BufSize);Das mag das Windows nicht wenn der Vector aufeinmal über 1 GB groß wird ...
-
Du hast 2 Sachen nicht kapiert:
1. Cooky nutzt gcount() um die Anzahl gelesener Bytes zu schreiben, du schreibst IMMER 100, egal wie viel gelesen wurden. Deswegen schreibst du Mist, der sich im Speicher dahinter befindet bzw davor im Buffer stand.
2. Bei Cookys Lösung kanst du die Buffergröße selbst angeben, dh der vector wird nur 1 GB groß, wenn du
copy_file<1024*1024*1024>(foo, bar);machst. Machst du das?
-
Wie wäre es damit:
std::ifstream reader("in_filename.xyz", std::ios::in|std::ios::binary); std::ofstream writer("out_filename.xyz", std::ios::out|std::ios::binary); writer << reader.rdbuf();
Die Puffergrößen kannst Du mit einem entsprechenden filebuf einstellen.
-
@ Ethon nein so hatte ich es nicht.^^
( 1402197877 = Die Größe meiner Datei )
copy_file<1402197877>(foo, bar);Aber mit 1024*1024*1024 geht es, aber warum geht es dann das hab ich noch nicht verstanden. Was macht der PC da intern anderes als wenn ich direkt die volle größe Schreibe?
Die gcount Funktion gefällt mir die löst ja schonmal ein Problem von mir.^^ (Die kannte ich noch gar nicht.)
@ Tachyon
In was für eine Block Größe schreibt rdbuf() ? Wobei eigentlich schreibt es ja nicht sondern gibt ein Stream Puffer Objekt was mit dem Stream verbunden ist zurück.
So steht es zumindest dort -> http://www.cplusplus.com/reference/iostream/ios/rdbuf/
-
cpy schrieb:
@ Ethon nein so hatte ich es nicht.^^
( 1402197877 = Die Größe meiner Datei )
copy_file<1402197877>(foo, bar);Aber mit 1024*1024*1024 geht es, aber warum geht es dann das hab ich noch nicht verstanden. Was macht der PC da intern anderes als wenn ich direkt die volle größe Schreibe?
Drück dich klar aus. Was passiert bzw. was passiert nicht? "Geht" und "Geht nicht" sind keine brauchbaren Problembeschreibungen.
@ Tachyon
In was für eine Block Größe schreibt rdbuf() ?
Schreibt er doch, dass Implementierungsdetails von der, ähh, Implementierung abhängen. Die du zur Not anpassen kannst.
Kürzliche intensive Vergleichstests hier im Forum haben ergeben, dass die von Tachyon vorgeschlagene Variante in der Regel sehr schnell ist. Sie kann nicht schneller sein als das gepufferte Kopieren, aber sie ist in der Regel auch nicht nennenswert langsamer (meisten war sie gleich schnell). Und beides ist natürlich viel schneller als naivere Varianten des Dateikopierens.
-
cpy schrieb:
@ Ethon nein so hatte ich es nicht.^^
( 1402197877 = Die Größe meiner Datei )
copy_file<1402197877>(foo, bar);Aber mit 1024*1024*1024 geht es, aber warum geht es dann das hab ich noch nicht verstanden. Was macht der PC da intern anderes als wenn ich direkt die volle größe Schreibe?
Die gcount Funktion gefällt mir die löst ja schonmal ein Problem von mir.^^ (Die kannte ich noch gar nicht.)
Das ist das Problem, du machst den Puffer so groß wie die Datei, aber das geht schlecht. Nimm doch ein konservatives Vielfaches von 4096.
copy_file<4096>(foo, bar);Der Code wird dann so oft (maximal) 4096 Byte große Häppchen kopieren, bis die Datei durch ist.
-
Es gibt da noch
boost::filesystem::copy_file.
-
@Ethon ich hab es jetzt mal versucht aber mit einer etwas kleineren Datei ( 625.987.585 Bytes )
Beim kopieren ist 1 Byte verloren gegangen o_O die neue Datei enthält nur 625.987.584 Bytes wie kann das sein?
#include <iostream> #include <fstream> #include <vector> using namespace std; template <std::size_t BufSize> void copy_file(std::istream& in, std::ofstream& out) { std::vector<char> buf(BufSize); while (in.read(&buf[0], buf.size())) out.write(&buf[0], in.gcount()); } int main() { ifstream file ("dbg.txt",ios::binary); ofstream f ("Kopie von dbg.txt",ios::binary); copy_file<4096>(file, f); return 0; }
-
Ich hab jetzt auch nochmal mit einer kleinen Datei probiert ( 9 MB Datei )
Da passiert das selbe es fehlt immer 1 Byte in der neuen Datei.Wenn ich jedoch immer Byte für Byte schriebe dann geht es.
-
Hab den Fehler gefunden es lag an der Kopfgesteuerten Schleife:
So funktioniert es:
template <std::size_t BufSize> void copy_file(std::istream& in, std::ofstream& out) { std::vector<char> buf(BufSize); do { in.read(&buf[0],BufSize); out.write(&buf[0],in.gcount() ); } while( ! in.eof() ); }
-
cpy schrieb:
@ Tachyon
In was für eine Block Größe schreibt rdbuf() ? Wobei eigentlich schreibt es ja nicht sondern gibt ein Stream Puffer Objekt was mit dem Stream verbunden ist zurück.
So steht es zumindest dort -> http://www.cplusplus.com/reference/iostream/ios/rdbuf/std::ifstream reader(argv[1], std::ios::in|std::ios::binary); char buff[4096]; reader.rdbuf()->pubsetbuf(buff, sizeof(buff));Und was Du tust ist auch nichts anderes als einen selbst gebastelten Puffer zu schreiben.
-
cpy schrieb:
Hab den Fehler gefunden es lag an der Kopfgesteuerten Schleife:
Dann kopier mal eine Datei ohne Inhalt.
Der Fehler lag garantiert in der üblichen Fehllogik aus schlechten Büchern.
while(Leseaktion) Verarbeiten; // richtig: Lesen, Bei Fehler abbrechen, richtige Daten verarbeiten while(!eof()) {Leseaktion; Verarbeiten;} // falsch: Bei Lesefehler(Dateiende) wird trotzdem was verarbeitet -> letzte Aktion doppelt
-
Na ja, da die Größe ja mit übergeben wird (und die dann 0 ist), sollte das kein Problem sein.
-
Bei einer Datei ohne Inhalt treten keine Probleme auf aber ich weiss jetzt was das Problem bei der anderen Lösung ist.
template <std::size_t BufSize> void copy_file(std::istream& in, std::ostream& out) { std::vector<char> buf(BufSize); while ( in.read(&buf[0], buf.size()) ) // Irgendwann kommt das EOF // und dann wird die letzte write // Operation übersprungen ... { out.write(&buf[0], in.gcount() ); } out.write(&buf[0], in.gcount() ); // Wenn hier nochmal write aufrufe dann // funktioniert es }Ich glaub ich schau nachher nochmal in das Stroustroup bin ja jetzt zuhause.
-
Ok, ich kannte den Code nicht, ich bin mal instinktiv von dem typischen Schlechtes-Lehrbuch-Pfusch ausgegangen, der hier 10x die Woche kommt. Im Stroustrup sollte es richtig erklärt sein.