Große Datei kopieren
-
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.