Kopiervorgang mit mehr als 1 Ziel
-
Hallo zusammen.
Ich soll ein kleines Tool schreiben, das 1 Quell-Laufwerk auf 3 Ziel-Laufwerke kopiert.
Also quasi die Dateien auf Laufwerk F: ausliest und dann gleichzeitig auf die Laufwerke G:, H: und I: kopiert.
(nicht binär sondern nur die Dateien)Ich bräuchte mal einen Ansatz wie man sowas am besten macht und ein paar grundsätzliche Ideen, da man mit Windows Boardmitteln ja immer nur von A nach B kopiert aber man nirgends mehr als 1 Ziel angeben kann.
Das Tool soll nicht 3 Kopiervorgänge hintereinander starten, sondern eben gleichzeitig auf alle 3 Ziele kopieren.
Geschrieben werden soll das ganze in C++ 6.0, allerdings bin ich so ein mittelprächtiger C++ Noob...

Thx.
mfg
Daniel
-
Mir fällt auf Anhieb kein Befehl ein, der in mehrere Ziele kopiert, da bleibt dir wohl nichts anderes übrig, als nacheinander in alle Ziele zu kopieren.
wenn du mit internen Mitteln kopieren willst (Quelle einlesen und in Zieldatei schreiben), kannst du auch nur die Ausgabe-Befehle duplizieren:
//Pseudocode ifstream fin(quelle); ofstream fout1(ziel1),fout2(ziel2); string zeile; while(getline(quelle,zeile)) { fout1<<zeile<<endl; fout2<<zeile<<endl; }(wobei - such mal nach "aufsplitten" im Forum, da findest du einen Ansatz, das zu automatisieren)
-
Also ich glaube nicht, dass man das irgendwie über ein Fremdprogramm wie xcopy machen kann, daher wird man es wohl mit C++ Mitteln machen müssen.
Der Code sieht schon mal recht intressant aus, aber wenn ich das als Nicht-C++-Freak richtig verstehe, kopiert das jetzt nur 1 bestimmte Datei.
Ich möchte ja alle Dateien auf dem Datenträger in allen Unterverzeichnissen kopieren.
Soll man das dann in eine Schleife schalten die systematisch durch den ganzen Verzeichnissbaum geht, oder wie?Und wie komme ich zu einer Fortschittsanzeige?
-
Ja, das mußt du in einer Schleife für jede Datei einzeln machen. (btw, auf WinAPI kannst du auch SHFileOperation() ausprobieren)
-
Es ist mögich gleichzeitig aus einer Datei zu lesen.
Du erstellst 3 Thread welche das kopieren übernehmen.
Hier gibt es dann eben viele Ansätze.
Jeder Thread öffnet die Datei und schreibst sie auf sein Laufwerk oder ein 4. Öffnet sie und übergibt den Inhalt an die Threads zum schreiben.
U.S:W.
-
Hallo.
Ich nochmal, ich habe das ganze jetzt mal umgesetzt und ich denke es wird so weit auch funktionieren, nur finde ich irgendwie einen Fehler in dieser Funktion nicht.
Das Problem ist recht einfach beschrieben:
Es wird komplett die ganze Ordnerstruktur und alles erzeugt, allerdings nur 1 Datei pro Ordner mit Inhalt, alle andern sind 0KB groß.
Ich weiß nur nicht warum?Beispiel:
\datei1.txt - 100KB
\datei2.txt - 200KB
\Ordner 1\datei3.txt - 300KB
\Ordner 1\datei4.txt - 400KB
\Ordner 2\datei5.txt - 500KB
\Ordner 2\datei6.txt - 600KBDie erste Datei die das Programm öffnet und kopieren will funktioniert, bei der 2ten geht die MessageBox auf "Datei kann nicht geöffnet werden" aber es steht nix in GetLastError() (Siehe Zeile 60 im Code).
Da ist anscheinend nur einfach NULL was GetLastError zurück liefert.
Dann sieht das Ziellaufwerk wie folgt aus:\datei1.txt - 100KB
\datei2.txt - 0KB
\Ordner 1\datei3.txt - 300KB
\Ordner 1\datei4.txt - 0KB
\Ordner 2\datei5.txt - 500KB
\Ordner 2\datei6.txt - 0KBWie gesagt, ich bin kein C++ Crack, warscheilich ist es total simpel und ich sehs nur nicht.
Ich bin mir auch mit data[1] nicht so sicher, aber wenn ichs größer mach, wird die Zieldatei länger als die Quelldatei.
int CTestanwendungDlg::CopyFiles(CString drive, int count_copy, int count){ CFileFind finder; BOOL bWorking; ifstream source_file1; ofstream target_file1, target_file2, target_file3; CString source_path1, target_path1, target_path2, target_path3; drive += _T("\\*.*"); bWorking = finder.FindFile(drive); while (bWorking && !cancelflag){ bWorking = finder.FindNextFile(); if (finder.IsDots()) continue; if (finder.IsDirectory()){ // Dies ist ein Directory CString str = finder.GetFilePath(); // Erstelle Ordner target_path1 = target1 + finder.GetFilePath().Right(finder.GetFilePath().GetLength() - 3); target_path2 = target2 + finder.GetFilePath().Right(finder.GetFilePath().GetLength() - 3); target_path3 = target3 + finder.GetFilePath().Right(finder.GetFilePath().GetLength() - 3); if(copy_to_target1){ CreateDirectory(target_path1, NULL); } if(copy_to_target2){ CreateDirectory(target_path2, NULL); } if(copy_to_target3){ CreateDirectory(target_path3, NULL); } // Kopiere Dateien dieses Ordners count_copy = CopyFiles(str, count_copy, count); } else{ // Dies ist eine Datei count_copy++; m_progress_ctrl.SetPos(count_copy); output.Format("Kopiere Datei %d von %d: %s", count_copy, count, finder.GetFilePath()); m_status_ctrl.SendMessage(WM_SETTEXT, 0, (LPARAM)(LPCTSTR)output); source_path1 = finder.GetFilePath(); target_path1 = target1 + finder.GetFilePath().Right(finder.GetFilePath().GetLength() - 3); target_path2 = target2 + finder.GetFilePath().Right(finder.GetFilePath().GetLength() - 3); target_path3 = target3 + finder.GetFilePath().Right(finder.GetFilePath().GetLength() - 3); source_file1.open(source_path1, ios::in | ios::binary); MessageBox("Öffne Datei "+ source_path1); if(!source_file1){ MessageBox ("Fehler beim öffnen der Datei." + GetLastError()); } if(copy_to_target1){ target_file1.open(target_path1, ios::out | ios::binary); } if(copy_to_target2){ target_file2.open(target_path2, ios::out | ios::binary); } if(copy_to_target3){ target_file3.open(target_path3, ios::out | ios::binary); } char data[1]; while(source_file1.read((char *) data, sizeof(data))){ if(copy_to_target1){ target_file1.write((char *) data, sizeof(data)); } if(copy_to_target2){ target_file2.write((char *) data, sizeof(data)); } if(copy_to_target3){ target_file3.write((char *) data, sizeof(data)); } } target_file1.clear(); target_file1.close(); target_file2.close(); target_file3.close(); source_file1.close(); } } finder.Close(); return count_copy; }
-
MessageBox ("Fehler beim öffnen der Datei." + GetLastError());Das funktioniert so nicht, denn GetLastError() liefert ein DWORD zurück und keinen CString oder const char *. Da geht die Stringkonkatenation natürlich in die Hose. Schau Dir mal CString::FormaT() an. Der nach Korrektur angezeigte Fehlercode sollte Dir dann hoffentlich weiterhelfen.
-
if(!source_file1){ output.Format("Fehler beim Öffnen der Datei: %d", GetLastError()); MessageBox (output); }"Fehler beim Öffnen der Datei: 0"
if(!source_file1){ output.Format("Fehler beim Öffnen der Datei: %s", GetLastError()); MessageBox (output); }"Fehler beim Öffnen der Datei: (null)"

-
Außerdem setzen (fast) nur WinAPI-Funktionen die GetLastError-Informationen, wenn etwas schiefgegangen ist - fstreams normalerweise nicht.
überblickt den Code Und ich sehe auch schon den Fehler - du hast vergessen, nach dem Schleifendurchlauf 'source_file1.clear();' aufzurufen, darum ist beim nächsten Anlauf (immer noch) dessen eofbit gesetzt.
PS: Und du kannst die Datei ruhig in etwas größeren Blöcken lesen und weitergeben.
-
Mit .close() gehts jetzt, danke.
Ich hab eine .txt Datei mit genau 1000 Zeilen und 200 Zeichen pro Zeile.
Sobald data[1] größer oder kleiner wird, wird die Datei auch größer oder kleiner.
Bei data[10000] sind es z.B. nur noch 981 Zeilen, mit data[100] fehlt in der letzten Zeile ein Teil.
-
Ja, read erwartet auch einen Datenblock von genau der angegebenen Größe - und scheitert, wenn es am Ende einen unvollständigen Datenblock übergeben bekommt. Vielleicht solltest du dir mal readsome() ansehen:
std::streamsize size; while( size=source_file1.readsome(data,sizeof(data)) , source_file1 )//ja ich weiß, diese Bedingung ist ein wenig tricky { if(copy_to_target1) target_file1.write(data, size); if(copy_to_target2) target_file2.write(data, size); if(copy_to_target3) target_file3.write(data, size); }