Kleines Kopierogramm kopiert Dateien aber Kopien sind nur 0 Byte groß! warum?
-
Hallo,
Ich habe ein kleines Kopierprogramm geschrieben
Hier ein Ausschnitt aus dem Programm:case IDM_T_START: { char Datei[512]; char Datei2[512]; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.lpstrFilter = FilterDef; ofn.nFilterIndex = 2; ofn.lpstrFile = PfadDatei; ofn.nMaxFile = sizeof(PfadDatei); ofn.lpstrFileTitle = Datei; ofn.nMaxFileTitle = 13; ofn.lpstrTitle = "Datei öffnen"; ofn.Flags = OFN_READONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; ofn.lpstrDefExt = "TXT"; if (GetOpenFileName(&ofn)) { hFile = CreateFile( PfadDatei, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile == INVALID_HANDLE_VALUE) { wsprintf( szMsg, "%s nicht gefunden!", PfadDatei); MessageBox(hWnd,szMsg, "Fehler", MB_ICONHAND | MB_OK); return (NULL); } CloseHandle( hFile ); //schließt wieder die Datei } wsprintf(szMsg, "Datei: %s kopieren?", PfadDatei); if(MessageBox(hWnd,szMsg ,ofn.lpstrFileTitle, MB_OKCANCEL | MB_ICONQUESTION)==IDOK) { strncpy(PfadDatei+ofn.nFileExtension,"BAK",4); ofn.hwndOwner = hWnd; ofn.lpstrFilter = FilterDef; ofn.nFilterIndex = 2; ofn.lpstrFile = PfadDatei; ofn.nMaxFile = sizeof(PfadDatei); ofn.lpstrFileTitle = Datei2; ofn.nMaxFileTitle = 13; ofn.Flags = OFN_CREATEPROMPT; ofn.lpstrDefExt = "BAK"; ofn.lpstrTitle = "Datei speichern"; } /* 25*/ if (GetSaveFileName(&ofn)) { hFile = CreateFile(Datei2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { MessageBox (hWnd, Datei2, "Fehler", MB_ICONHAND | MB_OK); return (NULL); } CloseHandle( hFile ); //schließt wieder die Datei } // Kopieren der Datei ohne vorhandene // Dateien zu überschreiben. //.................................................. if ( CopyFile( PfadDatei, Datei2, TRUE ) ) { wsprintf( szMsg, //wenn Kopiern möglich war "%s wurde nach %s kopiert", PfadDatei, Datei2); MessageBox(hWnd,szMsg, "Erfolgreiche Kopie", MB_ICONINFORMATION | MB_OK); } else // wenn Kopiern nicht möglich war { if ( GetLastError() == ERROR_FILE_EXISTS && MessageBox( hWnd, "Datei ist vorhanden.\n" "Datei überschreiben?", Datei2, MB_YESNO | MB_ICONQUESTION ) == IDYES ) //fragen ob Datei überschriben werden soll { // bei Taste Ja: // Kopieren der Datei und überschreiben // der vorhandenen Datei. //............................ CopyFile( PfadDatei, Datei2, FALSE ); if ( CopyFile == INVALID_HANDLE_VALUE) { // falls nicht übeschrieben werden kann // Fehlermeldung wsprintf( szMsg, "%s konnte nicht nach %s kopiert werden", PfadDatei,Datei2); MessageBox(hWnd,szMsg, "Fehler", MB_ICONHAND | MB_OK); return (NULL); } wsprintf( szMsg, "%s wurde nach %s kopiert", PfadDatei, Datei2); MessageBox(hWnd,szMsg, "Erfolgreiche Kopie", MB_ICONINFORMATION | MB_OK); // wenn Überschrieben werden konnte } } } /*==========================================================================*/ break;
Wenn man eine Datei kopieren möchte, dann klickt man auf "Start"
Dann öffnet sich ein "Datei öffnen" Menü.
Da kann man sich eine Datei aussuchen, die man kopieren möchte.
Nachdem man das gemacht hat, wird nachgefragt ob man z.B die Datei xyz.tst kopieren möchte. Bei "OK" öffnet sich ein "Datei speichern" Menü.
Hier kann man den Namen der kopierten Datei eingeben.
Es wird der Dateiname vorgeschlagen die auch die zu Kopierende Datei hat, nur mit der Endung: BAT z.B. : xyz.bat
Nach Rückfrage, wird die Datei kopiert.
Nur leider, in diesem Programm, wird die Dateiinhalt nicht mit kopiert!
Die Datei ist nur 0 Byte groß.Woran kann das liegen ?
Ich habe schon im Internet gesucht, aber nichts gefunden.Gruß Anktech
-
ofn.lpstrDefExt = "*.BAK";
-
Danke für deine Hilfe,
hat leider nicht geholfen.Gruß Anktech
-
if ( CopyFile == INVALID_HANDLE_VALUE)
-
Mit dem Code ist viel im Argen.
-
ofn.nMaxFileTitle = 13;
ist verdächtig. Willst du wirklich nur 13 Zeichen erlauben? -
Du setzt bei beiden Dialogen
ofn.lpstrFile = PfadDatei;
D.h. es wird beim Open Dialog der komplette Pfad nachPfadDatei
reinkopiert, und beim Save-Dialog wirdPfadDatei
wieder überschrieben. -
Danach überschreibst du selbst die Extension von
PfadDatei
, ohne den Pfad vorher gesichert zu haben. -
Bei
if (GetOpenFileName(&ofn))
fehlt ein else-Zweig der abbricht. -
Bei
if (MessageBox(hWnd,szMsg ,ofn.lpstrFileTitle, MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
fehlt ebenso der abbrechende else-Zweig. -
Das selbe nochmal bei
if (GetSaveFileName(&ofn))
uswusf.
Würde jetzt wirklich zu lange dauern Schritt für Schritt zu erklären was da alles schief geht.
Im Endeffekt funktioniert das Kopieren nicht, und du bekommst keine Fehlermeldung weil die Abfrageif (CopyFile == INVALID_HANDLE_VALUE)
völliger Quatsch ist (den Hinweis hat asdf123 ja schon gegeben).
(Tip:CopyFile == INVALID_HANDLE_VALUE
vergleicht die Adresse der FunktionCopyFile
mit der KonstanteINVALID_HANDLE_VALUE
. (Was eigentlich gar nicht funktionieren sollte, da das eine ein Funktionszeiger ist und das andere ein Datenzeiger...)
Auf jeden Fall wird dabei immerfalse
rauskommen.Also fang mal damit an, und kämpf dich dann weiter vor:
// Quatsch: // CopyFile( PfadDatei, Datei2, FALSE ); // if ( CopyFile == INVALID_HANDLE_VALUE) // Besser: BOOL copyFileResult = CopyFile( PfadDatei, Datei2, FALSE ); if (!copyFileResult)
-
-
Hallo asdf123 und hustbaer, dass Kopierprogramm Funktioniert jetzt
Danke für eure Hilfe.Ein Fehler lag an:
( CopyFile == INVALID_HANDLE_VALUE)
ich hab es dann zu:
BOOL copyFileResult = CopyFile( PfadDatei, Datei2, FALSE ); if (!copyFileResult)
gemacht
Danke für den Tipp:Ein zweiter großer Fehler lag daran:
if ( CopyFile( PfadDatei, Datei2, TRUE ) )
Hier wurde die PfadDatei in Datei kopiert
Ein weiter Fehler war der überflüssige Code
hFile = CreateFile(Datei2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { MessageBox (hWnd, Datei2, "Fehler", MB_ICONHAND | MB_OK); return (NULL); } CloseHandle( hFile ); //schließt wieder die Datei }
Hier habe ich jetzt mal den funktionierenden code:
case IDM_T_START: { char Datei[512]; char Datei2[512]; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.lpstrFilter = FilterDef; ofn.nFilterIndex = 2; ofn.lpstrFile = PfadDatei; ofn.nMaxFile = sizeof(PfadDatei); ofn.lpstrFileTitle = Datei; ofn.nMaxFileTitle = 512; //geändert ofn.lpstrTitle = "Datei öffnen"; ofn.Flags = OFN_READONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; ofn.lpstrDefExt = "TXT"; if (GetOpenFileName(&ofn)) { hFile = CreateFile( PfadDatei, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile == INVALID_HANDLE_VALUE) { wsprintf( szMsg, "%s nicht gefunden!", Datei); //geändert MessageBox(hWnd,szMsg, "Fehler", MB_ICONHAND | MB_OK); return (NULL); } CloseHandle( hFile ); //schließt wieder die Datei } else //geändert { return (NULL); } wsprintf(PfadDatei1,"%s",PfadDatei); //geändert // Hier nimmt PfadDatei1 den Pfad und Dateinamen von PfadDatei an wsprintf(szMsg, "Datei: %s kopieren?", Datei); if(MessageBox(hWnd,szMsg ,ofn.lpstrFileTitle, MB_OKCANCEL | MB_ICONQUESTION)==IDOK) { strncpy(PfadDatei+ofn.nFileExtension,"bak",4); ofn.hwndOwner = hWnd; ofn.lpstrFilter = FilterDef; ofn.nFilterIndex = 2; ofn.lpstrFile = PfadDatei; ofn.nMaxFile = sizeof(PfadDatei); ofn.lpstrFileTitle = Datei2; ofn.nMaxFileTitle = 512; //geändert ofn.Flags = OFN_CREATEPROMPT; ofn.lpstrDefExt = "*.bak"; //geändert ofn.lpstrTitle = "Datei speichern"; ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT; } else //geänedrt { wsprintf( szMsg, "%s wurde nicht kopiert",Datei2); MessageBox (hWnd, Datei2, "Fehler", MB_ICONHAND | MB_OK); return (NULL); } if (GetSaveFileName(&ofn)) { /* hFile = CreateFile(Datei2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { MessageBox (hWnd, Datei2, "Fehler", MB_ICONHAND | MB_OK); return (NULL); } CloseHandle( hFile ); //schließt wieder die Datei } */ // Kopieren der Datei ohne vorhandene // Dateien zu überschreiben. //.................................................. if ( CopyFile( PfadDatei1, PfadDatei, TRUE ) ) //geändert { wsprintf( szMsg, //wenn Kopiern möglich war "Orginal: %s\nKopie: %s", PfadDatei1, PfadDatei); MessageBox(hWnd,szMsg, "Erfolgreiche Kopie", MB_ICONINFORMATION | MB_OK); } else // wenn Kopiern nicht möglich war { if ( GetLastError() == ERROR_FILE_EXISTS && MessageBox( hWnd, "Datei ist vorhanden.\n" "Datei überschreiben?", Datei2, MB_YESNO | MB_ICONQUESTION ) == IDYES ) //fragen ob Datei überschriben werden soll { // bei Taste Ja: // Kopieren der Datei und überschreiben // der vorhandenen Datei. //............................ BOOL copyFileResult = CopyFile //geändert (PfadDatei1, PfadDatei, FALSE); if (!copyFileResult) { // falls nicht übeschrieben werden kann // Fehlermeldung wsprintf( szMsg, "%s konnte nicht nach %s kopiert werden", PfadDatei1,PfadDatei); MessageBox(hWnd,szMsg, "Fehler", MB_ICONHAND | MB_OK); return (NULL); } wsprintf( szMsg, "Orginal: %s\nKopie: %s", PfadDatei1, PfadDatei); MessageBox(hWnd,szMsg, "Erfolgreiche Kopie", MB_ICONINFORMATION | MB_OK); // wenn Überschrieben werden konnte } } } } /*==========================================================================*/
PfadDatei muss übrigens im save Dialog bleiben, sonst schlägt er nicht erneut den Dateinamen mit der Endung "bat" vor.
Über weiter Verbesserungen, Vorschläge oder Kritiken zu den Programm, würde ich mich freuen.Gruß Anktech
-
hustbaer schrieb:
Mit dem Code ist viel im Argen ...
So ist es!
Wie hustbaer schon angemerkt hat gibt es eine Menge Schrott im Code.
Es fängt bereits hier an:char Datei[512]; char Datei2[512];
Statt char sollte es besser TCHAR heissen, da die Felder sonst bei UNICODE zu
klein sind. (UNICODE wird hier offensichtlich auch verwendet siehe wsprintf()).
Statt 515 sollte man besser MAX_PATH oder einen anderen mit define festgelegten
Namen verwenden.ofn.lpstrFile = PfadDatei; ofn.nMaxFile = sizeof(PfadDatei); ofn.lpstrFileTitle = Datei; ofn.nMaxFileTitle = 512; //geändert
lpstrFile ist ein LPTSTR und sollte das Ergebnis enthalten, wenn
GetOpenFileName() mit OK beendet wurde.Ohne die Deklaration von PfadDatei zu kennen, ist das nicht zu prüfen, aber
in nMaxFile und nMaxFileTitle sollten natürlich die Goessen der
zugehörigen Speicherbereiche in Zeichen (characters) stehen; und weder eine
feste Zahl noch die Groesse des Pointers noch die Anzahl in Byte.Ich würde auch davon abraten für beide Dialoge den gleichen Speicher für
lpstrFile zu verwenden.wsprintf(PfadDatei1,"%s",PfadDatei); //geändert ... strncpy(PfadDatei+ofn.nFileExtension,"bak",4); ofn.lpstrFile = PfadDatei; ofn.nMaxFile = sizeof(PfadDatei);
Hier wird eine Kopie angelegt, aber dann nicht verwendet. Statt
dessen wird die Extension des Originalnamens überschrieben.EDIT: Ich sehe gerade, das mal wsprintf und mal strncpy zum Einsatz kommt.
Mal davon abgesehen, das strncpy möglicherweise die terminierende Null abschneiden
könnte sollte natürlich auch hier ein UNICODE copy zum Einsatz kommen.
(wcscpy oder besser _tcscpy )
-
Danke merano für deine Hilfe
So ich habe jetzt einiges an dem Code geändert.char Datei[512]; char Datei2[512];
Habe ich jetzt in:
char Datei[MAX_PATH] = ""; char DateiKopie[MAX_PATH] = "";
geändert.
TCHAR kennt mein Compiler nicht.
(Borland 5.02 . Ja ich weiß der ist sehr alt, von 1997, aber sehr gut!)
oder gibt es dafür eine bestimmte Header Datei?lpstrFile ist ein LPTSTR und sollte das Ergebnis enthalten, wenn GetOpenFileName() mit OK beendet wurde.
Das habe ich jetzt nicht verstanden!
Die Deklaration von PfadDatei sieht so aus:
char PfadDatei[1024]; char PfadDateiKopie[1024];
Die größte wird doch mit sizeof, auf die passende Größe abgeschnitten:
ofn.nMaxFile = sizeof(PfadDatei);
oder wie sollte ich das machen?
Ich würde auch davon abraten für beide Dialoge den gleichen Speicher für lpstrFile zu verwenden.
Das habe ich auch nicht verstanden?
das mit den wsprintf zu Dateinamenskopie habe ich geändert
strcpy(PfadDateiKopie,PfadDatei);
oder wie wende ich stattdessen wcscpy oder _tcscpy an?
Hat jemand ein Beispiel dafür?Hier jetzt nochmal die Deklaration von PfadDatei:
#include <commdlg.h> char PfadDatei[1024]; char PfadDateiKopie[1024]; OPENFILENAME ofn; char FilterDef[256] = "Batch (*.BAT)\0*.BAT\0Alle (*.*)\0*.*\0Backup\0*.BAK;*.SIK\0Text (*.TXT)\0*.TXT\0" ;
und hier nochmal der verbesserte Programmausschnitt:
case IDM_T_START: { char Datei[MAX_PATH] = ""; char DateiKopie[MAX_PATH] = ""; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.lpstrFilter = FilterDef; ofn.nFilterIndex = 2; ofn.lpstrFile = PfadDatei; ofn.nMaxFile = sizeof(PfadDatei); ofn.lpstrFileTitle = Datei; ofn.nMaxFileTitle = MAX_PATH; //geändert ofn.lpstrTitle = "Datei öffnen"; ofn.Flags = OFN_READONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; ofn.lpstrDefExt = "TXT"; if (GetOpenFileName(&ofn)) { hFile = CreateFile( PfadDatei, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile == INVALID_HANDLE_VALUE) { wsprintf( szMsg, "%s nicht gefunden!", Datei); //geändert MessageBox(hWnd,szMsg, "Fehler", MB_ICONHAND | MB_OK); return (NULL); } CloseHandle( hFile ); //schließt wieder die Datei } else //geändert { return (NULL); } strcpy(PfadDateiKopie,PfadDatei); //geändert // Hier nimmt PfadDateiKopie den Pfad und Dateinamen von PfadDatei an wsprintf(szMsg, "Datei: %s kopieren?", Datei); if(MessageBox(hWnd,szMsg ,ofn.lpstrFileTitle, MB_OKCANCEL | MB_ICONQUESTION)==IDOK) { // strncpy(PfadDatei+ofn.nFileExtension,"bak",4); ofn.hwndOwner = hWnd; ofn.lpstrFilter = FilterDef; ofn.nFilterIndex = 2; ofn.lpstrFile = PfadDateiKopie; ofn.nMaxFile = sizeof(PfadDateiKopie); ofn.lpstrFileTitle = DateiKopie; ofn.nMaxFileTitle = MAX_PATH; //geändert ofn.Flags = OFN_CREATEPROMPT; ofn.lpstrDefExt = "*.bak"; //geändert ofn.lpstrTitle = "Datei speichern"; ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT; } else //geänedrt { return (NULL); } if (GetSaveFileName(&ofn)) { // Kopieren der Datei ohne vorhandene // Dateien zu überschreiben. //.................................................. if ( CopyFile( PfadDatei, PfadDateiKopie, TRUE ) ) //geändert { wsprintf( szMsg, //wenn Kopiern möglich war "Orginal: %s\nKopie: %s", PfadDatei, PfadDateiKopie); MessageBox(hWnd,szMsg, "Erfolgreiche Kopie", MB_ICONINFORMATION | MB_OK); } else // wenn Kopiern nicht möglich war { if ( GetLastError() == ERROR_FILE_EXISTS && MessageBox( hWnd, "Datei ist vorhanden.\n" "Datei überschreiben?", DateiKopie, MB_YESNO | MB_ICONQUESTION ) == IDYES ) //fragen ob Datei überschriben werden soll { // bei Taste Ja: // Kopieren der Datei und überschreiben // der vorhandenen Datei. //............................ BOOL copyFileResult = CopyFile //geändert (PfadDatei, PfadDateiKopie, FALSE); if (!copyFileResult) { // falls nicht übeschrieben werden kann // Fehlermeldung wsprintf( szMsg, "%s konnte nicht nach %s kopiert werden", PfadDatei, PfadDateiKopie); MessageBox(hWnd,szMsg, "Fehler", MB_ICONHAND | MB_OK); return (NULL); } wsprintf( szMsg, "Orginal: %s\nKopie: %s", PfadDatei, PfadDateiKopie); MessageBox(hWnd,szMsg, "Erfolgreiche Kopie", MB_ICONINFORMATION | MB_OK); // wenn Überschrieben werden konnte } } } } /*==========================================================================*/
-
Anktech schrieb:
TCHAR kennt mein Compiler nicht...oder gibt es dafür eine bestimmte Header Datei?
Ja klar tchar.h.
Üblicherweise ist da sowas definiert:
#ifdef UNICODE #ifndef _TCHAR_DEFINED typedef wchar_t WCHAR; typedef WCHAR TCHAR, *PTCHAR; typedef WCHAR TBYTE , *PTBYTE ; #define _TCHAR_DEFINED #endif typedef LPWSTR PTSTR, LPTSTR; #else #ifndef _TCHAR_DEFINED typedef char TCHAR, *PTCHAR; typedef unsigned char TBYTE , *PTBYTE ; #define _TCHAR_DEFINED #endif typedef LPSTR PTSTR, LPTSTR, PUTSTR, LPUTSTR; #endif /* UNICODE */
Unicode ist (lt. Google) im ANSI-C-Standard enthalten und wurde auch wide
character genannt. Der Datentyp für Unicode-Character heißt "wchar_t". Die Header-
Datei zum Einbinden heißt "wchar.h" und enthält z.B. Funktionen wie "wcslen()".Ein LPTSTR ist ein LongPointer auf TCHAR String und wird je nachdem
ob UNICODE verwendet wird als char oder als wchar_t interpretiert.Vermutlich hat Borland das auch irgendwie eingebaut.
_tcscpy, strcpy, wcscpy, _mbscpy siehe
http://msdn.microsoft.com/en-us/library/kk6xf663.aspx
Anktech schrieb:
... oder wie wende ich stattdessen wcscpy oder _tcscpy an?
Verwendung genau wie die einfache ANSI-Version, nur das das statt
char ein TCHAR definiert ist. Sollte der Boprland Compiler nur
char kennen ist das kein Problem, Dein Code wird aber schnell
inkompatibel wenn das mit einem neueren Compiler compiliert wird.Microsoft unterscheidet z.B. bei GetOpenFileName zwischen
GetOpenFileNameW (Unicode) und GetOpenFileNameA (ANSI), wobei die richtige
Version aufgrund der Projekeinstellung automatisch verwendet wird.http://msdn.microsoft.com/en-us/library/windows/desktop/ms646927.aspx
Anktech schrieb:
char PfadDatei[1024]; char PfadDateiKopie[1024];
Es sind immer noch mit char und Ziffern kodierte Pfadlängen im Code.
Auch hier wäre es besser zu schreiben:
TCHAR PfadDatei[MAX_PATH];
Übrigens: Die Konstante MAX_PATH bezeichnet die maximale Länge des kompletten Pfades und das beinhaltet auch den Dateinamen und die Extension.
Es gibt auch hier einen interessanten Artikel:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspxEine gute Beschreibung (englisch) findet sich auch hier:
http://www.codeproject.com/Articles/76252/What-are-TCHAR-WCHAR-LPSTR-LPWSTR-LPCTSTR-etc
-
Danke merano für deine Hilfe.
Die Include Datei tchar.h ist im Borland Compiler vorhanden.
Daher klappte es jetzt auch mit:TCHAR PfadDatei[MAX_PATH];
könnte man da auch nicht:
TCHAR PfadDatei[MAX_PATH] = "";
schreiben?
Auch habe ich jetzt, _tcscpy anstatt strcpy verwendet:
_tcscpy(PfadDateiKopie,PfadDatei);
Dann habe ich:
ofn.nMaxFile = MAX_PATH;
anstatt:
ofn.nMaxFile = sizeof(PfadDatei);
verwendet.
Somit müsste das Programm jetzt fehlerfrei zu sein!
Gruß Anktech