Folgende Funktion kann als einfache Vorlage genutzt werden um geöffnete Textfiles zu schließen und eventuell anschließend zu löschen.
Parameter | Beschreibung |
---|---|
const FILE ** fileToClose | Adresse der FILE-Variable |
const char * fileNameToDelete | FQ Filename, das gelöscht werden soll |
int modus | Zum Schließen / zum Schließen+Löschen |
int maxRetry | Maximale Zahl der Versuche, File zu schließen/löschen |
int retryDelay | Pause in Sekunden zwischen den Versuchen |
Alle im Quelltext festkodierte Konstanten sind nur Beispielswerte. Bei konkreter Umsetzung sollen die Werte verwendet werden, die für die jeweilige Anwendung für sinnvoll erscheinen. Noch sinnvoller wäre anstelle von festkodierten Konstanten globale Variablen oder Makros einzusetzen, damit solche Werte auf einfache Weise anwendungsweit angepaßt werden könnten.
int done_EinAusFile (const FILE ** fileToClose, const char * fileNameToDelete, int modus, int maxRetry, int retryDelay) { int rc = RC_OK; int retry; int notDeleted; // Validierung: Vorhandensein von Variablen (darf kein NULL sein) if (!fileToClose) rc = RC_ERROR; // Validierung: Werte dürfen sich nur im definierten Bereich bewegen if (!(modus == FILE_CLOSE || modus == FILE_DELETE)) rc = RC_ERROR; // Darf 3 oder 4 sein if ((maxRetry < 1) || (maxRetry > 32767)) rc = RC_ERROR; // 1 bis 15^2-1 mal if ((retryDelay < 0) || (retryDelay > 86400)) rc = RC_ERROR; // 24 Std x 60 Min x 60 Sek // Validierung: Pointer-Variablen: Werte nur im definierten Bereich if (fileNameToDelete) if (strlen(fileNameToDelete) == 0 || strlen(fileNameToDelete) > FILENAME_LAENGE) rc = RC_ERROR; // Länge des Filenames if (fileToClose) if (!(*fileToClose)) rc = RC_ERROR; // File MUSS bereits geöffnet sein // Validierung: Kombination von Werten if (modus == FILE_DELETE) if (!fileNameToDelete) rc = RC_ERROR; // Beim Löschen muss der Filename angegeben werden if (rc) fprintf(stderr, "done_EinAusFile(): Validierungsfehler.\n"); if (!rc) // File schließen { fprintf(stdout, "done_EinAusFile(): File [%s] wird geschlossen...\n", fileNameToDelete ? fileNameToDelete : "(FileName nicht angegeben)"); for (retry = maxRetry; (retry > 0) && (*fileToClose); retry--) // Evtl. mehrere Versuche { if (fclose(*fileToClose) == 0) *fileToClose = NULL; // Falls erfolgreich geschlossen, den Zeiger zurücksetzen if ((retry > 1) && (*fileToClose)) sleep(retryDelay); // Falls Mißerfolg - kurze Pause einlegen (außer nach dem letzten Versuch). } // for (retry) if (!(*fileToClose)) fprintf(stdout, "done_EinAusFile(): ...erfolgreich\n"); else rc = RC_ERROR; if (rc) fprintf(stderr, "done_EinAusFile(): Fehler beim Schließen des Files aufgetreten.\n"); } // if if ((!rc) && (modus == FILE_DELETE)) // File löschen { fprintf(stdout, "done_EinAusFile(): File [%s] wird gelöscht...\n", fileNameToDelete); for (retry = maxRetry, notDeleted = 1; (retry > 0) && (notDeleted); retry--) // Evtl. mehrere Versuche { if (remove(fileNameToDelete) == 0) notDeleted = 0; // Falls erfolgreich gelöscht, den Flag zurücksetzen if ((retry > 1) && (notDeleted)) sleep(retryDelay); // Falls Mißerfolg - kurze Pause einlegen (außer nach dem letzten Versuch). } // for (retry) if (!notDeleted) fprintf(stdout, "done_EinAusFile(): ...erfolgreich\n"); else rc = RC_ERROR; if (rc) fprintf(stderr, "done_EinAusFile(): Fehler beim Löschen des Files [%s] aufgetreten.\n", fileNameToDelete); } // if fflush(stderr); fflush(stdout); return rc; } // done_EinAusFile(..)
wobei:
RC_OK und RC_ERROR, FILE_CLOSE und FILE_DELETE, FILENAME_LAENGE sind die vom Benutzer definierten Makros.
Beispiel eines Aufrufs:
#define FILENAME_LAENGE 8191 // TextFile schliessen #define FILE_CLOSE 3 // TextFile schliessen und loeschen #define FILE_DELETE 4 // Beim Öffnen maximal so viele Versuchen unternehmen: #define FILE_RETRY 3 // Zwischen den Wiederholungen so viele Sekunden warten: #define FILE_DELAY 1 FILE * fileInputDatei = NULL; // Input-Datei FILE * fileOutputDatei = NULL; // Output-Datei char parFileNameInputDatei [FILENAME_LAENGE + 1]; // FileName für die Input-Datei char parFileNameOutputDatei [FILENAME_LAENGE + 1]; // FileName für die Output-Datei int app_Done (int rc_Init, int rc_Run) { int rc = RC_OK; int rc_FileClose = RC_OK; fprintf(stdout, "app_Done(): Ein-/Ausgabe-Files werden geschlossen.\n"); // Die Input-Datei schließen if (fileInputDatei) { rc = done_EinAusFile(&fileInputDatei, parFileNameInputDatei, FILE_CLOSE, FILE_RETRY, FILE_DELAY); if (rc) fprintf(stderr, "app_Done(): ERROR (unkritisch): Das Schließen des Files [%s] ist fehlgeschlagen.\n", parFileNameInputDatei); } // if // Die Output-Datei schließen und löschen if (fileOutputDatei) { rc = done_EinAusFile(&fileOutputDatei, parFileNameOutputDatei, FILE_DELETE, FILE_RETRY, FILE_DELAY); if (rc) fprintf(stderr, "app_Done(): ERROR (kritisch): Das Schließen des Files [%s] ist fehlgeschlagen.\n", parFileNameAbkDatei); } // if if (rc_FileClose) errorMsgFatal(TODO_KEINABBRUCH, "app_Done(): Eine der Dateien konnte nicht geschlossen werden. Sie ist möglicherweise beschädigt und kann nicht verwendet werden."); fflush(stderr); return rc; } // app_Done()
wobei:
errorMsgFatal() - eine Funktion, die kritische Meldungen ausgibt (und z.B. im Syslog protokolliert) und je nach Parameter, falls nötig, den Prozess zwangsweise abbricht.
Und ab und zu fflush(stderr); bzw. fflush(stdout); auch nicht vergessen.
Stand: 24.02.2010
— : Jürgen Kreick
EOF