Arbeiten mit Dateien in C, Eingabe und Ausgabe in eine Datei in C. Arbeiten mit Textdateien. Abrufen von Verzeichnisinformationen

In diesem Artikel erfahren Sie, wie Sie in C-Programmen Daten aus Dateien lesen und Informationen in Dateien schreiben. Dateien in C werden verwendet, um das Ergebnis eines C-Programms zu speichern und beim erneuten Starten des Programms zu verwenden. Sie können beispielsweise Berechnungsergebnisse und Spielstatistiken speichern.
Um mit Dateien in C arbeiten zu können, müssen Sie die Bibliothek stdio.h einbinden
#enthalten
Arbeiten mit Datei in C Sie müssen gemäß dem Beispiel einen Zeiger auf die Datei angeben
FILE *Dateizeigername;
Zum Beispiel
DATEI *fin;
Gibt einen Fin-Zeiger auf eine Datei an
Als nächstes müssen Sie die Datei öffnen und mit dem Dateizeiger verknüpfen. Um eine Datei in C zum Lesen zu öffnen, verwenden Sie den Befehl
Dateizeigername= fopen("Dateipfad", "r");
Zum Beispiel der folgende Befehl
fin = fopen("C:\\Benutzer\\user\\Desktop\\data.txt", "r");
öffnet die Datei data.txt, die sich auf dem Desktop im Pfad C:\\Benutzer\\Benutzer\\Desktop befindet. Um den Pfad zur Datei herauszufinden, können Sie die Datei mit der Maus auswählen und mit der rechten Maustaste klicken und wählen Sie Dateieigenschaften aus. Der Abschnitt „Speicherort“ gibt den Pfad zur Datei an. Bitte beachten Sie, dass in C der Pfad durch zwei Schrägstriche angegeben wird.
Nachdem Sie mit der Datei in C gearbeitet haben, müssen Sie sie mit dem Befehl schließen
fclose(Dateizeigername)

Lesen von Informationen aus einer Textdatei in C

Um russische Zeichen aus einer Datei lesen zu können, müssen Sie die Arbeit mit Kyrillisch mithilfe des Befehls konfigurieren
setlocale(LC_ALL, "Russisch");

In diesem Fall müssen Sie #include am Anfang des Programms einfügen

fscanf()-Operator

Ein Wort daraus lesen Datei in C Der Befehl fscanf() wird verwendet. Dieser Befehl ähnelt dem Befehl zur Eingabe von Informationen über die Tastatur, nur der erste Parameter ist ein Zeiger auf die Datei
fscanf(file pointer,"%data input format1% data input format2...",&variable1,&variable2...);
Zum Beispiel der Befehl
fscanf(fin,"%d%d%d",&a,&b,&c);
liest einen String aus drei Integer-Variablen aus einer Datei, die mit einem Dateizeiger fin verknüpft ist
Schauen wir uns ein Beispiel für ein Programm an, das Informationen aus einer Textdatei data.txt, in der drei Zahlenspalten geschrieben sind, liest und in Arrays schreibt. Jede Informationsspalte verfügt über ein eigenes Array. Details zu.
#enthalten
#enthalten
hauptsächlich()
(int a;
int b;
int c;
int i;
// einen Zeiger auf die Datei definieren
DATEI *fin;
// Datei zum Lesen öffnen
fin = fopen("C:\\Benutzer\\user\\Desktop\\data.txt", "r");
// Zeile für Zeile aus der Datei lesen
für (i=0;i<3;i++)
{
// Einen String aus drei Dateiwerten lesen und in Arrays schreiben
fscanf(fin,"%d%d%d",&a[i],&b[i],&c[i]);
}
// Arrays auf dem Bildschirm anzeigen
für (i=0;i<3;i++)
{
printf("%d %d %d ",a[i],b[i],c[i]);
}
getch();
// die Datei schließen
fclose(fin);
}

Zeilenweises Lesen von Informationen aus einer Datei in SI. Funktion fgets()

Der fscanf()-Operator liest ein Wort aus einer Datei, d. h. zum ersten angetroffenen Leerzeichen.
Um die gesamte Zeile aus einer Datei in C zu lesen, verwenden Sie die Konstruktion
if (NULL != fgets (String-Variable, String-Länge, Dateizeiger))
{
Aktionen beim Lesen einer Zeile
}

Zum Beispiel ein C-Programm, das zwei Zeilen aus einer Datei liest und sie auf dem Bildschirm anzeigt
#enthalten
#enthalten
#enthalten
hauptsächlich()
{
// String-Variablen setzen
char st1;
char st2;
//Definiere einen Zeiger auf die Datei
DATEI *fin;
// Arbeit mit kyrillischem Alphabet einrichten
setlocale(LC_ALL, "Russisch");
// Datei zum Lesen öffnen
fin = fopen("C:\\data.txt", "r");
// die erste Zeile aus der Datei lesen
if (NULL != fgets (st1, 100, fin))
{
// die Zeichenfolge auf dem Bildschirm anzeigen
printf("%s",st1);)
// die zweite Zeile aus der Datei lesen
if (NULL != fgets (st2, 100, fin))
{
// die Zeichenfolge auf dem Bildschirm anzeigen
printf("%s",st2);)
// Datei zum Lesen schließen
fclose(fin);
}

Schreiben von Informationen in eine Textdatei in C

Zum Aufzeichnen von Daten in eine Datei in C, müssen Sie die Datei im Aufnahmemodus öffnen
Dateizeigername= fopen("Dateipfad", "w");
Um in eine Zeile in einer Textdatei zu schreiben, verwenden Sie den Befehl fprnitf(), der dem Befehl in C ähnelt, nur dass der erste Parameter ein Zeiger auf die Datei ist
fprintf (Dateizeigername, „% Eingabeformat“, Variablen);
Schreiben Sie beispielsweise den Wert der Variablen a in die Datei out.txt
a=10;
fout = fopen("C:\\Benutzer\\user\\Desktop\\out.txt", "w");
fprintf(fout,"%d", a);

Ein Beispiel für ein C-Programm, das zwei Zahlen anfordert und diese beiden Zahlen und ihre Summe in die Datei out.txt schreibt

#enthalten
#enthalten

hauptsächlich()
(int a;
int b;
int c;
DATEI *fout;
fout = fopen("C:\\Benutzer\\user\\Desktop\\out.txt", "w");
printf("Geben Sie die erste Zahl ein");
scanf("%d", &a);
printf("zweite Zahl eingeben");
scanf("%d", &b);
c=a+b;
fprintf(fout,"%d %d %d",a,b,c);
getch();
fclose(fout);
}

Stichworte: Textdateien, fopen, fclose, feof, setbuf, setvbuf, fflush, fgetc, fprintf, fscanf, fgets, gepufferter Stream, ungepufferter Stream.

Arbeiten mit Textdateien

Die Arbeit mit einer Textdatei ähnelt der Arbeit mit der Konsole: Mit formatierten Eingabefunktionen speichern wir Daten in einer Datei, mit formatierten Ausgabefunktionen lesen wir Daten aus einer Datei. Es gibt viele Nuancen, die wir später betrachten werden. Die wichtigsten Operationen, die durchgeführt werden müssen, sind:

  • 1. Öffnen Sie die Datei, damit darauf zugegriffen werden kann. Dementsprechend können Sie es zum Lesen, Schreiben, Lesen und Schreiben, Umschreiben oder Schreiben bis zum Ende der Datei usw. öffnen. Wenn Sie eine Datei öffnen, können auch eine Reihe von Fehlern auftreten – die Datei existiert möglicherweise nicht, es handelt sich möglicherweise um den falschen Dateityp, Sie haben möglicherweise keine Berechtigung zum Arbeiten mit der Datei usw. All dies muss berücksichtigt werden.
  • 2. Direktes Arbeiten mit der Datei – Schreiben und Lesen. Auch hier müssen wir bedenken, dass wir nicht mit Arbeitsspeicher arbeiten, sondern mit einem gepufferten Stream, der seine eigenen Besonderheiten hinzufügt.
  • 3. Schließen Sie die Datei. Da es sich bei der Datei um eine Ressource außerhalb des Programms handelt, bleibt sie, wenn sie nicht geschlossen wird, weiterhin im Speicher hängen, möglicherweise auch nach dem Schließen des Programms (z. B. ist es nicht möglich, eine geöffnete Datei zu löschen oder Änderungen vorzunehmen). usw.). Darüber hinaus ist es manchmal erforderlich, eine Datei nicht zu schließen, sondern „erneut zu öffnen“, um beispielsweise den Zugriffsmodus zu ändern.

Darüber hinaus gibt es eine Reihe von Aufgaben, bei denen wir nicht auf den Inhalt der Datei zugreifen müssen: Umbenennen, Verschieben, Kopieren usw. Leider enthält der C-Standard keine Beschreibung von Funktionen für diese Anforderungen. Sie sind natürlich für jede Compiler-Implementierung verfügbar. Das Lesen des Inhalts eines Verzeichnisses (Ordner, Verzeichnis) ist auch ein Zugriff auf eine Datei, da der Ordner selbst eine Datei mit Metainformationen ist.

Manchmal ist es notwendig, einige Hilfsoperationen durchzuführen: an die gewünschte Stelle in der Datei verschieben, sich die aktuelle Position merken, die Länge der Datei bestimmen usw.

Um mit einer Datei arbeiten zu können, benötigen Sie ein FILE-Objekt. Dieses Objekt speichert die Kennung des Dateistreams und die zu seiner Verwaltung erforderlichen Informationen, einschließlich eines Zeigers auf seinen Puffer, einer Dateipositionsanzeige und Statusanzeigen.

Das FILE-Objekt ist selbst eine Struktur, auf seine Felder sollte jedoch nicht zugegriffen werden. Das portable Programm muss die Datei als abstraktes Objekt behandeln, das den Zugriff auf den Dateistream ermöglicht.

Die Erstellung und Zuweisung von Speicher für ein Objekt vom Typ FILE erfolgt mit der Funktion fopen oder tmpfile (es gibt noch andere, aber wir konzentrieren uns nur auf diese).

Die Funktion fopen öffnet eine Datei. Es erhält zwei Argumente – einen String mit der Dateiadresse und einen String mit dem Dateizugriffsmodus. Der Dateiname kann entweder absolut oder relativ sein. fopen gibt einen Zeiger auf ein FILE-Objekt zurück, das für den weiteren Zugriff auf die Datei verwendet werden kann.

FILE* fopen(const char* Dateiname, const char* Modus);

Öffnen wir beispielsweise eine Datei und schreiben „Hello World“ hinein

#enthalten #enthalten #enthalten void main() ( //Mithilfe der Dateivariablen greifen wir auf die Datei FILE *file; //Öffnen Sie eine Textdatei mit Schreibberechtigungen file = fopen("C:/c/test.txt", "w+t") ; //Schreibe in die Datei fprintf(file, "Hello, World!"); //Schließe die Datei fclose(file); getch(); )

Die fopen-Funktion selbst reserviert Speicher für das Objekt; die Reinigung erfolgt durch die fclose-Funktion. Die Datei muss geschlossen werden; sie wird nicht von selbst geschlossen.

Die Funktion fopen kann eine Datei im Text- oder Binärmodus öffnen. Der Standardwert ist Text. Der Zugriffsmodus kann wie folgt sein

Dateizugriffsoptionen.
Typ Beschreibung
R Lektüre. Die Datei muss vorhanden sein.
w Schreiben Sie eine neue Datei. Wenn bereits eine Datei mit demselben Namen vorhanden ist, geht ihr Inhalt verloren.
A Schreiben Sie bis zum Ende der Datei. Positionierungsoperationen (fseek, fsetpos, frewind) werden ignoriert. Die Datei wird erstellt, wenn sie nicht existiert.
r+ Lesen und Aktualisieren. Sie können sowohl lesen als auch schreiben. Die Datei muss vorhanden sein.
w+ Aufzeichnung und Aktualisierung. Eine neue Datei wird erstellt. Wenn bereits eine Datei mit demselben Namen vorhanden ist, geht ihr Inhalt verloren. Sie können sowohl schreiben als auch lesen.
a+ Beitrag beenden und aktualisieren. Positionierungsvorgänge sind schreibgeschützt und werden bei Schreibvorgängen ignoriert. Wenn die Datei nicht vorhanden war, wird eine neue erstellt.

Wenn es notwendig ist, die Datei im Binärmodus zu öffnen, wird der Buchstabe b am Ende der Zeile hinzugefügt, zum Beispiel „rb“, „wb“, „ab“ oder für den gemischten Modus „ab+“, „ wb+“, „ab+“. Anstelle von b können Sie den Buchstaben t hinzufügen, dann wird die Datei im Textmodus geöffnet. Es kommt auf die Umsetzung an. Im neuen C-Standard (2011) bedeutet der Buchstabe x, dass fopen fehlschlagen sollte, wenn die Datei bereits existiert. Ergänzen wir unser altes Programm: Öffnen Sie die Datei erneut und überlegen Sie, was wir dort geschrieben haben.

#enthalten #enthalten #enthalten void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); fprintf(file, "Hello, World!"); fclose(file); file = fopen("C:/c/test.txt", "r"); fgets(buffer, 127, file); printf("%s", buffer); fclose(file); getch(); )

Anstelle der fgets-Funktion könnten Sie auch fscanf verwenden, Sie müssen jedoch bedenken, dass damit nur die Zeile bis zum ersten Leerzeichen gelesen werden kann.
fscanf(file, „%127s“, buffer);

Anstatt eine Datei zu öffnen und zu schließen, können Sie auch die Funktion freopen verwenden, die die Datei mit neuen Zugriffsrechten „erneut öffnet“.

#enthalten #enthalten #enthalten void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); fprintf(file, "Hello, World!"); freopen("C:/ c/test.txt", "r", file); fgets(buffer, 127, file); printf("%s", buffer); fclose(file); getch(); )

Die Funktionen fprintf und fscanf unterscheiden sich von printf und scanf nur dadurch, dass sie als erstes Argument einen Zeiger auf die DATEI verwenden, in die sie Daten ausgeben oder aus der sie Daten lesen. Es lohnt sich gleich hinzuzufügen, dass die Funktionen printf und scanf leicht durch die Funktionen fprintf und fscanf ersetzt werden können. Im Betriebssystem (wir betrachten die gängigsten und geeignetsten Betriebssysteme) gibt es drei Standardstreams: den Standardausgabestream stdout, den Standardeingabestream stdin und den Standardfehlerausgabestream stderr. Sie werden beim Start der Anwendung automatisch geöffnet und mit der Konsole verknüpft. Beispiel

#enthalten #enthalten #enthalten void main() ( int a, b; fprintf(stdout, "Geben Sie zwei Zahlen ein\n"); fscanf(stdin, "%d", &a); fscanf(stdin, "%d", &b); if (b == 0) ( fprintf(stderr, "Fehler: Division durch Null"); ) else ( fprintf(stdout, "%.3f", (float) a / (float) b); ) getch(); )

Fehler beim Öffnen der Datei

Wenn der Aufruf der fopen-Funktion fehlschlägt, wird NULL zurückgegeben. Bei der Arbeit mit Dateien treten häufig Fehler auf. Deshalb müssen wir jedes Mal, wenn wir eine Datei öffnen, das Ergebnis der Arbeit überprüfen

#enthalten #enthalten #enthalten #define ERROR_OPEN_FILE -3 void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); if (file == NULL) ( printf("Fehler beim Öffnen file"); getch(); exit(ERROR_OPEN_FILE); ) fprintf(file, "Hello, World!"); freopen("C:/c/test.txt", "r", file); if (file = = NULL) ( printf("Fehler beim Öffnen der Datei"); getch(); exit(ERROR_OPEN_FILE); ) fgets(buffer, 127, file); printf("%s", buffer); fclose(file); getch() ; )

Das Problem entsteht, wenn mehrere Dateien gleichzeitig geöffnet werden: Wenn eine davon nicht geöffnet werden kann, müssen auch die anderen geschlossen werden

DATEI *Eingabedatei, *Ausgabedatei; vorzeichenloses m, n; ohne Vorzeichen i, j; inputFile = fopen(INPUT_FILE, READ_ONLY); if (inputFile == NULL) ( printf("Fehler beim Öffnen der Datei %s", INPUT_FILE); getch(); exit(3); ) outputFile = fopen(OUTPUT_FILE, WRITE_ONLY); if (outputFile == NULL) ( printf("Fehler beim Öffnen der Datei %s", OUTPUT_FILE); getch(); if (inputFile != NULL) ( fclose(inputFile); ) exit(4); ) ...

In einfachen Fällen können Sie direkt vorgehen, wie im vorherigen Codeabschnitt. In komplexeren Fällen werden Methoden verwendet, die RAII aus C++ ersetzen: Wrapper oder Compiler-Funktionen (Bereinigung in GCC) usw.

Datenpufferung

Wie bereits erwähnt, werden Daten bei der Ausgabe zunächst in einem Puffer abgelegt. Der Puffer wird gelöscht

  • 1) Wenn es voll ist
  • 2) Wenn der Stream geschlossen ist
  • 3) Wenn wir ausdrücklich darauf hinweisen, dass es notwendig ist, den Puffer zu löschen (auch hier gibt es Ausnahmen :)).
  • 4) Wird auch gelöscht, wenn das Programm erfolgreich abgeschlossen wurde. Gleichzeitig werden alle Dateien geschlossen. Im Falle eines Laufzeitfehlers kann dies nicht passieren.

Sie können das Entladen des Puffers erzwingen, indem Sie die Funktion fflush(File *) aufrufen. Schauen wir uns zwei Beispiele an – mit und ohne Reinigung.

#enthalten #enthalten #enthalten void main() ( FILE *file; char c; file = fopen("C:/c/test.txt", "w"); do ( c = getch(); fprintf(file, "%c", c ); fprintf(stdout, "%c", c); //fflush(file); ) while(c != "q"); fclose(file); getch(); )

Kommentieren Sie den Flush-Anruf aus. Öffnen Sie zur Laufzeit die Textdatei und sehen Sie sich das Verhalten an.

Sie können einen Dateipuffer selbst zuweisen, indem Sie Ihre eigene Größe festlegen. Dies geschieht über die Funktion

Void setbuf(FILE * stream, char * buffer);

Dies erfordert eine bereits geöffnete DATEI und einen Zeiger auf einen neuen Puffer. Die Größe des neuen Puffers darf nicht kleiner als BUFSIZ sein (auf der aktuellen Arbeitsstation beträgt BUFSIZ beispielsweise 512 Byte). Wenn Sie NULL als Puffer übergeben, wird der Stream ungepuffert. Sie können die Funktion auch nutzen

Int setvbuf(FILE * stream, char * buffer, int mode, size_t size);

die einen Puffer beliebiger Größe akzeptiert. Der Modus kann die folgenden Werte annehmen

  • _IOFBF- Vollständige Pufferung. Daten werden in die Datei geschrieben, wenn diese voll ist. Beim Lesen gilt der Puffer als voll, wenn eine Eingabeoperation angefordert wird und der Puffer leer ist.
  • _IOLBF- lineare Pufferung. Daten werden in die Datei geschrieben, wenn sie voll ist oder wenn ein Zeilenumbruchzeichen auftritt. Beim Lesen wird der Puffer bis zum Zeilenumbruchzeichen gefüllt, wenn eine Eingabeoperation angefordert wird und der Puffer leer ist.
  • _IONBF– keine Pufferung. In diesem Fall werden die Parameter Größe und Puffer ignoriert.
Bei Erfolg gibt die Funktion 0 zurück.

Beispiel: Lassen Sie uns unseren eigenen Puffer festlegen und sehen, wie das Lesen aus einer Datei erfolgt. Lassen Sie die Datei kurz sein (so etwas wie Hello, World!), und wir lesen sie Zeichen für Zeichen

#enthalten #enthalten #enthalten void main() ( FILE *input = NULL; char c; char buffer = (0); input = fopen("D:/c/text.txt", "rt"); setbuf(input, buffer); while ( !feof(input)) ( c = fgetc(input); printf("%c\n", c); printf("%s\n", buffer); _getch(); ) fclose(input); )

Es ist ersichtlich, dass sich die Daten bereits im Puffer befinden. Das Lesen Zeichen für Zeichen erfolgt aus dem Puffer.

feof

Funktion int feof(FILE * stream); gibt true zurück, wenn das Ende der Datei erreicht ist. Die Funktion ist praktisch, wenn Sie die gesamte Datei von Anfang bis Ende durchgehen müssen. Es sei eine Datei mit Textinhalt text.txt vorhanden. Wir lesen die Datei Zeichen für Zeichen und zeigen sie auf dem Bildschirm an.

#enthalten #enthalten #enthalten void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Fehler beim Öffnen der Datei") ; _getch(); exit(0); ) while (!feof(input)) ( c = fgetc(input); fprintf(stdout, "%c", c); ) fclose(input); _getch(); )

Alles wäre in Ordnung, aber die feof-Funktion funktioniert nicht richtig... Dies liegt daran, dass das Konzept des „Ende der Datei“ nicht definiert ist. Ein Fehler, der bei der Verwendung von feof häufig auftritt, besteht darin, dass die zuletzt gelesenen Daten zweimal gedruckt werden. Dies liegt daran, dass die Daten in den Eingabepuffer geschrieben werden, der letzte Lesevorgang mit einem Fehler erfolgt und die Funktion den alten gelesenen Wert zurückgibt.

#enthalten #enthalten #enthalten void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Fehler beim Öffnen der Datei") ; _getch(); exit(0); ) while (!feof(input)) ( fscanf(input, "%c", &c); fprintf(stdout, "%c", c); ) fclose(input); _getch(); )

Dieses Beispiel wird (höchstwahrscheinlich) fehlschlagen und das letzte Zeichen der Datei zweimal drucken.

Die Lösung besteht darin, feof nicht zu verwenden. Speichern Sie beispielsweise die Gesamtzahl der Datensätze oder nutzen Sie die Tatsache, dass Funktionen von fscanf usw. normalerweise die Anzahl der korrekt gelesenen und abgeglichenen Werte zurückgeben.

#enthalten #enthalten #enthalten void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Fehler beim Öffnen der Datei") ; _getch(); exit(0); ) while (fscanf(input, "%c", &c) == 1) ( fprintf(stdout, "%c", c); ) fclose(input); _getch() ; )

Beispiele

1. Eine Datei enthält zwei Zahlen – die Abmessungen des Arrays. Füllen wir die zweite Datei mit einem Array von Zufallszahlen.

#enthalten #enthalten #enthalten #enthalten //Dateinamen und Berechtigungen #define INPUT_FILE "D:/c/input.txt" #define OUTPUT_FILE "D:/c/output.txt" #define READ_ONLY "r" #define WRITE_ONLY "w" //Maximalwert für Array size #define MAX_DIMENSION 100 //Fehler beim Öffnen der Datei #define ERROR_OPEN_FILE -3 void main() ( FILE *inputFile, *outputFile; unsigned m, n; unsigned i, j; inputFile = fopen(INPUT_FILE, READ_ONLY); if ( inputFile == NULL) ( printf("Fehler beim Öffnen der Datei %s", INPUT_FILE); getch(); exit(ERROR_OPEN_FILE); ) OutputFile = fopen(OUTPUT_FILE, WRITE_ONLY); if (outputFile == NULL) ( printf("Fehler Datei %s öffnen", OUTPUT_FILE); getch(); //Wenn die Datei zum Lesen geöffnet werden konnte, muss sie geschlossen werden if (inputFile != NULL) ( fclose(inputFile); ) exit(ERROR_OPEN_FILE); ) fscanf (inputFile, "%ud %ud", &m, &n); if (m > MAX_DIMENSION) ( m = MAX_DIMENSION; ) if (n > MAX_DIMENSION) ( n = MAX_DIMENSION; ) srand(time(NULL)); für (i = 0; ich< n; i++) { for (j = 0; j < m; j++) { fprintf(outputFile, "%8d ", rand()); } fprintf(outputFile, "\n"); } //Закрываем файлы fclose(inputFile); fclose(outputFile); }

2. Der Benutzer kopiert die Datei und wählt zunächst den Betriebsmodus aus: Die Datei kann entweder auf der Konsole ausgegeben oder in eine neue Datei kopiert werden.

#enthalten #enthalten #enthalten #define ERROR_FILE_OPEN -3 void main() ( FILE *origin = NULL; FILE *output = NULL; char filename; int mode; printf("Enter filename: "); scanf("%1023s", filename); origin = fopen (filename, "r"); if (origin == NULL) ( printf("Fehler beim Öffnen der Datei %s", Dateiname); getch(); exit(ERROR_FILE_OPEN); ) printf("enter mode: "); scanf( "%d", &mode); if (mode == 1) ( printf("Enter filename: "); scanf("%1023s", filename); output = fopen(filename, "w"); if (output = = NULL) ( printf("Fehler beim Öffnen der Datei %s", Dateiname); getch(); fclose(origin); exit(ERROR_FILE_OPEN); ) ) else ( Output = stdout; ) while (!feof(origin)) ( fprintf (output, "%c", fgetc(origin)); ) fclose(origin); fclose(output); getch(); )

3. Der Benutzer gibt Daten über die Konsole ein und diese werden in eine Datei geschrieben, bis die Esc-Taste gedrückt wird. Schauen Sie sich das Programm an und sehen Sie. wie es sich verhält, wenn Sie die Rücktaste eingeben: Was wird in die Datei ausgegeben und was wird auf der Konsole ausgegeben.

#enthalten #enthalten #enthalten #define ERROR_FILE_OPEN -3 void main() ( FILE *output = NULL; char c; Output = fopen("D:/c/test_output.txt", "w+t"); if (output == NULL) ( printf ("Fehler beim Öffnen der Datei"); _getch(); exit(ERROR_FILE_OPEN); ) for (;;) ( c = _getch(); if (c == 27) ( break; ) fputc(c, Output); fputc( c, stdout); ) fclose(output); )

4. Die Datei enthält ganze Zahlen. Finden Sie das Maximum davon. Machen wir uns die Tatsache zunutze, dass die Funktion fscanf die Anzahl der korrekt gelesenen und übereinstimmenden Objekte zurückgibt. Die Nummer 1 sollte jedes Mal zurückgegeben werden.

#enthalten #enthalten #enthalten #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; int num, maxn, hasRead; input = fopen("D:/c/input.txt", "r"); if (input == NULL) ( printf("Fehler beim Öffnen der Datei"); _getch(); exit(ERROR_FILE_OPEN); ) maxn = INT_MIN; hasRead = 1; while (hasRead == 1) ( hasRead = fscanf(input, "%d", &num); if (hasRead != 1) ( continue; ) if (num >

Eine andere Lösung besteht darin, Zahlen zu lesen, bis wir das Ende der Datei erreichen.

#enthalten #enthalten #enthalten #enthalten #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; int num, maxn, hasRead; input = fopen("D:/c/input.txt", "r"); if (input == NULL) ( printf("Fehler beim Öffnen der Datei"); _getch(); exit(ERROR_FILE_OPEN); ) maxn = INT_MIN; while (!feof(input)) ( fscanf(input, "%d", &num); if (num > maxn ) ( maxn = num; ) ) printf("max number = %d", maxn); fclose(input); _getch(); )

5. Die Datei enthält Wörter: russisches Wort, Tabellierung, englisches Wort, in mehreren Zeilen. Der Benutzer gibt ein englisches Wort ein, das russische muss ausgegeben werden.

Die Übersetzungsdatei sieht in etwa so aus

Sonne Sonne
Bleistift
Kugelschreiber Bleistift
Tür Tür
Fensterfenster
Stuhl Stuhl
Sessel

und in cp866-Kodierung (OEM 866) gespeichert. Wichtig: Auch das letzte Wortpaar endet mit einem Zeilenvorschub.

Der Algorithmus ist wie folgt: Wir lesen eine Zeile aus einer Datei, suchen ein Tabulatorzeichen in der Zeile, ersetzen das Tabulatorzeichen durch eine Null, kopieren ein russisches Wort aus dem Puffer, kopieren ein englisches Wort aus dem Puffer und prüfen die Gleichheit.

#enthalten #enthalten #enthalten #enthalten #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; char buffer; char enWord; char ruWord; char usrWord; unsigned index; int length; int wasFound; input = fopen("D:/c/input.txt ", "r"); if (input == NULL) ( printf("Fehler beim Öffnen der Datei"); _getch(); exit(ERROR_FILE_OPEN); ) printf("Wort eingeben: "); fgets(usrWord, 127, stdin ); wasFound = 0; while (!feof(input)) ( fgets(buffer, 511, input); length = strlen(buffer); for (index = 0; index< length; index++) { if (buffer == "\t") { buffer = "\0"; break; } } strcpy(ruWord, buffer); strcpy(enWord, &buffer); if (!strcmp(enWord, usrWord)) { wasFound = 1; break; } } if (wasFound) { printf("%s", ruWord); } else { printf("Word not found"); } fclose(input); _getch(); }

6. Zählen Sie die Anzahl der Zeilen in der Datei. Wir lesen die Datei Zeichen für Zeichen und zählen die Anzahl der „\n“ Zeichen, bis wir auf das EOF-Zeichen stoßen. EOF ist ein Sonderzeichen, das anzeigt, dass die Eingabe abgeschlossen ist und keine Daten mehr gelesen werden müssen. Im Fehlerfall gibt die Funktion einen negativen Wert zurück.
HINWEIS: EOF ist vom Typ int, daher müssen Sie int verwenden, um die Zeichen zu lesen. Darüber hinaus ist der Wert von EOF nicht im Standard definiert.

#define _CRT_SECURE_NO_WARNINGS #include #enthalten #enthalten int cntLines(const char *filename) ( intlines = 0; int any; //any ist vom Typ int, weil EOF vom Typ int ist! FILE *f = fopen(filename, "r"); if (f == NULL ) ( return -1; ) do ( any = fgetc(f); //printf("%c", any);//debug if (any == "\n") (lines++; ) ) while(any ! = EOF); ​​​​fclose(f); returnlines; ) void main() ( printf("%d\n", cntLines("C:/c/file.txt")); _getch(); )

Ru-Cyrl 18-Tutorial Sypachev S.S. 14.04.1989 [email protected] Stepan Sypachev Studenten

Immer noch nicht klar? – Schreiben Sie Fragen an die Mailbox

Der von , entwickelte E/A-Mechanismus entspricht nicht dem heute allgemein akzeptierten Stil der objektorientierten Programmierung und verwendet außerdem häufig Zeigeroperationen, die in modernen sicheren Codeausführungsumgebungen als potenziell unsicher gelten. Eine Alternative bei der Entwicklung von Anwendungsanwendungen ist der Mechanismus der Standard-I/O-Klassen, der vom C++-Sprachstandard bereitgestellt wird.

Dateien öffnen

Die am häufigsten verwendeten Klassen sind ifstream zum Lesen, ofstream zum Schreiben und fstream zum Ändern von Dateien.

Alle Thread-E/A-Klassen sind indirekt vom gemeinsamen Vorfahren ios abgeleitet und erben dessen Funktionalität vollständig. Somit wird der Dateiöffnungsmodus durch das Datenelement des Aufzählungstyps open_mode angegeben, der wie folgt definiert ist:

Enum open_mode ( app, binär, in, out, trunc, ate );

Nachfolgend sind die möglichen Werte der Flags und ihr Zweck aufgeführt.

Um beispielsweise eine Datei mit dem Namen test.txt zu öffnen und Daten in Binärform zu lesen, würden Sie schreiben:

ifstream-Datei; file.open("test.txt", ios::in | ios::binary);

Mit dem logischen ODER-Operator (|) können Sie einen Modus mit einer beliebigen Kombination von Flags erstellen. Damit Sie beim Öffnen einer Datei per Eintrag nicht versehentlich eine bereits vorhandene Datei mit demselben Namen überschreiben, müssen Sie folgendes Formular verwenden:

Ofstream-Datei; file.open("test.txt", ios::out | ios::app);

Es wird davon ausgegangen, dass die entsprechende Header-Datei im Projekt enthalten ist:

#enthalten

Um zu überprüfen, ob die Datei erfolgreich geöffnet wurde, können Sie das Konstrukt verwenden

If (!file) ( //Behandlung von Dateiöffnungsfehlern)

Einschluss- und Extraktionsoperatoren

Wird in Dateiverarbeitungsklassen überschrieben Einschlussoperator (<<) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:

Datei<< "Это строка текста";

Sie können eine Textzeichenfolge auch in Teilen schreiben:

Datei<< "Это " << "строка " << "текста";

Die endl-Anweisung beendet die Zeileneingabe mit einem Wagenrücklauf:

Datei<< "Это строка текста" << endl;

Mit dem Include-Operator ist es einfach, die Werte von Variablen oder Array-Elementen in eine Datei zu schreiben:

Ofstream-Datei("Temp.txt"); char buff = „Textarray enthält Variablen“; int vx = 100; float pi = 3,14159; Datei<< buff << endl << vx << endl << pi << endl;

Als Ergebnis der Ausführung des Codes werden drei Zeilen der Textdatei Temp.txt gebildet:

Das Textarray enthält die Variablen 100 3.14159

Beachten Sie, dass numerische Werte als Textzeichenfolgen und nicht als Binärwerte in die Datei geschrieben werden.

Abrufoperator(>>) erzeugt den gegenteiligen Effekt. Es scheint, dass Sie zum Extrahieren von Zeichen aus der zuvor geschriebenen Datei „Temp.txt“ Code wie den folgenden schreiben würden:

Ifstream-Datei("Temp.txt"); Char-Buff; int vx; float pi; file >> buff >> vx >> pi;

Der Extraktionsoperator stoppt jedoch beim ersten Trennzeichen, auf das er trifft (Leerzeichen, Tabulator oder Zeilenumbruch). Beim Parsen des Satzes „Textarray enthält Variablen“ wird also nur das Wort „Text“ in das Buff-Array geschrieben, der Leerraum wird ignoriert und das Wort „Array“ wird zum Wert der gesamten vx-Variablen und des Codes Die Ausführung wird „schiefgehen“ und die Datenstruktur unvermeidlich verletzen. Als nächstes zeigen wir bei der Diskussion der ifstream-Klasse, wie man das Lesen der Datei aus dem vorherigen Beispiel richtig organisiert.

ifstream-Klasse: Dateien lesen

Wie der Name schon sagt, ist die ifstream-Klasse für die Eingabe eines Dateistreams konzipiert. Die Hauptmethoden der Klasse sind unten aufgeführt. Die meisten davon werden von der istream-Klasse geerbt und überladen, um die übergeordnete Funktionalität zu erweitern. Beispielsweise kann die Get-Funktion je nach Aufrufparameter nicht nur ein einzelnes Zeichen, sondern auch einen Block von Zeichen lesen.

Jetzt ist klar, wie das vorherige Beispiel geändert werden muss, damit die Verwendung des Datenextraktionsoperators das erwartete Ergebnis liefert:

Ifstream-Datei("Temp.txt"); Char-Buff; int vx; float pi; file.getline(buff, sizeof(buff)); Datei >> vx >> pi:

Die getline-Methode liest die erste Zeile der Datei bis zum Ende und der >>-Operator weist den Variablen Werte zu.

Das folgende Beispiel zeigt das Hinzufügen von Daten zu einer Textdatei und das anschließende Lesen der gesamten Datei. Aus den in erläuterten Gründen wird anstelle von while(!file2.eof()) eine while(1)-Schleife verwendet.

#enthalten #enthalten Verwenden des Namensraums std; int main() ( ofstream file; file.open("test.txt",ios::out|ios::app); if (!file) ( cout<< "File error - can"t open to write data!"; cin.sync(); cin.get(); return 1; } for (int i=0; i<10; i++) file << i << endl; file.close(); ifstream file2; file2.open("test.txt", ios::in); if (!file2) { cout << "File error - can"t open to read data!"; cin.sync(); cin.get(); return 2; } int a,k=0; while (1) { file2 >>a; if (file2.eof()) break; cout<< a << " "; k++; } cout << endl << "K=" << k << endl; file2.close(); cin.sync(); cin.get(); return 0; }

Das folgende Beispiel zeigt eine Schleife, die Zeilen aus der Datei test.txt liest und auf der Konsole anzeigt.

#enthalten #enthalten Verwenden des Namensraums std; int main() ( ifstream file; // eine Stream-Objektdatei erstellen file.open("test.txt"); // die Datei zum Lesen öffnen if (!file) return 1; // beim Öffnen einen Fehler zurückgeben char str; // statischer Zeilenpuffer // Zeilen in einer Schleife lesen und anzeigen, bis eof while (!file.getline(str, sizeof(str)).eof()) cout<< str << endl; // вывод прочитанной строки на экран cin.sync(); cin.get(); return 0; }

Dieser Code unter Windows-Betriebssystemen hängt auch vom Vorhandensein eines Newline-Zeichens in der letzten Zeile der Datei ab; zuverlässiger wäre es, dies zu tun:

While (1) ( if (file.eof()) break; file.getline(str, sizeof(str)); cout<< str << endl; }

Explizite Aufrufe der open- und close-Methoden sind nicht erforderlich. Tatsächlich ermöglicht Ihnen der Aufruf des Konstruktors mit einem Argument, die Datei sofort zu öffnen, zum Zeitpunkt der Erstellung des Thread-Dateiobjekts:

Ifstream-Datei("test.txt");

Anstelle der Methode close können Sie den Operator delete verwenden, der automatisch den Destruktor des Dateiobjekts aufruft und die Datei schließt. Der While-Schleifencode sorgt für ordnungsgemäße End-of-File-Prüfungen.

ofstream-Klasse: Dateien schreiben

Die ofstream-Klasse dient zur Ausgabe von Daten aus einem Dateistream. Im Folgenden sind die Hauptmethoden dieser Klasse aufgeführt.

Der zuvor beschriebene Einschlussoperator eignet sich zum Organisieren des Schreibens in eine Textdatei:

Ofstream-Datei("temp.txt"); if (!file) return; für (int i=1; i<=3; i++) file << "Строка " << i << endl; file.close();

Binärdateien

Im Prinzip werden Binärdaten wie Textdaten behandelt. Der Unterschied besteht darin, dass Binärdaten, wenn sie in eine bestimmte logische Struktur geschrieben werden, aus einer Datei in eine Variable desselben Strukturtyps gelesen werden müssen.

Der erste Parameter der Schreib- und Lesemethoden (die Adresse des Schreib-/Leseblocks) muss vom Zeichenzeigertyp char * sein, daher ist eine explizite Konvertierung des Adresstyps der Struktur void * erforderlich. Der zweite Parameter gibt an, dass die Binärblöcke der Datei unabhängig von der tatsächlichen Datensatzlänge eine konstante Bytegröße haben. Die folgende Anwendung bietet ein Beispiel für die Erstellung und Anzeige von Daten in einem einfachen Notizbuch. Die Dateieinträge werden dann sequentiell gelesen und auf der Konsole angezeigt.

#enthalten #enthalten #enthalten Verwenden des Namensraums std; struct Notes ( // Notebook-Datenstruktur char Name; // vollständiger Name char Phone; // phone int Age; // age ); int main() ( setlocale(LC_ALL, "Russian"); Notes Note1= ("Der schreckliche Ioann Wassiljewitsch", "nicht installiert", 60 ); Notes Note2= ("Godunov Boris Fedorovich", "095-111-2233" , 30 ); Notes Note3= ( "Romanov Petr Mikhailovich", "812-333-2211 ", 20 ); ofstream ofile("Notebook.dat", ios::binary); ofile.write((char*)&Note1, sizeof (Notes)); // 1. Block ofile.write((char*)&Note2, sizeof(Notes)); // 2. Block ofile.write((char*)&Note3, sizeof(Notes)); // 3. Block ofile.close(); // die aufgezeichnete Datei schließen ifstream ifile("Notebook.dat", ios::binary); Notes Note; // strukturierte Variable char str; // statischer String-Puffer // Zeilen in a lesen und anzeigen Schleife bis eof while (!ifile.read((char*)&Note, sizeof(Notes)).eof()) ( sprintf(str, "%s\tPhone: %s\tAge: %d" , Note.Name, Note.Phone, Note.Age); cout<< str << endl; } ifile.close(); // закрыть прочитанный файл cin.sync(); cin.get(); return 0; }

Als Ergebnis der Ausführung dieses Codes wird eine Binärdatei Notebook.dat aus drei Blöcken zu je 80 Bytes gebildet (vorausgesetzt, die Zeichen sind Einzelbytes). Natürlich können Sie auch andere Threading-Methoden verwenden und beliebige Operationen an den Feldern einer bestimmten Datenstruktur ausführen.

fstream-Klasse: Zufälliger Dateizugriff

Nehmen wir an, wir haben 100 Einträge in unserem Notizbuch und wollen den 50. zählen. Natürlich können Sie eine Schleife organisieren und alle Datensätze vom ersten bis zum angegebenen lesen. Offensichtlich besteht eine gezieltere Lösung darin, den Positionszeiger der POS-Datei direkt auf Eintrag 50 zu setzen und daraus zu lesen:

Ifstream ifile("Notebook.dat", ios::binary); int pos = 49 * sizeof(Notes); ifile.seekg(pos); // Suche nach dem 50. Notes Note-Eintrag; //Notes – die oben beschriebene „Record“-Struktur ifile.read((char*)&Note, sizeof(Notes));

Solche Suchvorgänge sind effektiv, wenn die Datei aus Datensätzen bekannter und konstanter Größe besteht. Um den Inhalt eines beliebigen Datensatzes zu ersetzen, müssen Sie den Ausgabestream im Änderungsmodus öffnen:

Ofstream ofile ("Notebook.dat", ios::binary | ios::ate); int pos = 49 * sizeof(Notes); ofile seep(pos); // Suche nach der 50. Note Notes Note50 = ("Yeltsin Boris Nikolaevich", "095-222-3322", 64); ofile.write((char*)&Note, sizeof(Notes)); // Ersatz

Wenn Sie das Flag ios::ate (oder ios::app) nicht angeben, wird beim Öffnen der Binärdatei Notebook.dat der vorherige Inhalt gelöscht!

Schließlich ist es möglich, eine Datei gleichzeitig zum Lesen/Schreiben zu öffnen, indem die Methoden verwendet werden, die die fstream-Streaming-Klasse von ihren Vorgängern geerbt hat. Da die fstream-Klasse von istream und ostream (übergeordneten Elementen von ifstream bzw. ofstream) abgeleitet ist, werden alle zuvor genannten Methoden in der Anwendung verfügbar.

Das folgende Beispiel zeigt die Neuanordnung des ersten und dritten Eintrags in der Datei Notebook.dat.

#enthalten #enthalten #enthalten Verwenden des Namensraums std; struct Notes (char Name; char Phone; int Age; ); int main() ( setlocale(LC_ALL, "Russian"); Notes Note1, Note3; // Datei zum gleichzeitigen Lesen/Schreiben öffnen fstream file("Notebook.dat", ios::binary | ios::in | ios: : out); file.seekg(2 * sizeof(Notes)); // Note3 finden und lesen file.read((char*)&Note3, sizeof(Notes)); file.seekg(0); // finden und lesen Note1 file.read((char*)&Note1, sizeof(Notes)); file.seekg(0); // Note1<== Note3 file.write((char*)&Note3, sizeof(Notes)); file.seekg(2 * sizeof(Notes)); // Note3 <== Note1 file.write((char*)&Note1, sizeof(Notes)); char str; // Считывать и отображать записи в цикле, пока не eof file.seekg(0); // вернуться к началу файла while (!file.read((char*)&Note1, sizeof(Notes)).eof()) { sprintf(str, "%s\tТел: %s\tВозраст: %d", Note1.Name, Note1.Phone, Note1.Age); cout << str << endl; } file.close(); cin.sync(); cin.get(); return 0; }

Im Konstruktor des Dateiobjekts müssen Sie die Flags ios::in und ios::out angeben, um gleichzeitige Lese- und Schreibvorgänge zu ermöglichen. Als Ergebnis der Ausführung dieses Codes werden der erste und dritte Eintrag in der Binärdatei Notebook.dat vertauscht.

Es gibt weitere Beispiele zum Thema.

Bisher haben wir bei der Ein- und Ausgabe von Daten mit Standard-Streams gearbeitet – der Tastatur und dem Monitor. Schauen wir uns nun an, wie die Sprache C das Empfangen von Daten aus Dateien und das Schreiben dieser Daten in diese implementiert. Bevor Sie diese Vorgänge ausführen können, müssen Sie die Datei öffnen und darauf zugreifen.

In der Programmiersprache C ist ein Zeiger auf eine Datei vom Typ FILE und seine Deklaration sieht folgendermaßen aus:
DATEI *meineDatei;

Andererseits öffnet die Funktion fopen() eine Datei an der als erstes Argument angegebenen Adresse im Lesemodus („r“), Schreibmodus („w“) oder Anhängemodus („a“) und gibt einen Zeiger zurück dazu zum Programm. Daher sieht der Vorgang zum Öffnen einer Datei und zum Verbinden mit dem Programm in etwa so aus:
myfile = fopen("hello.txt", "r");

Beim Lesen oder Schreiben von Daten in eine Datei wird über einen Dateizeiger (in diesem Fall myfile) darauf zugegriffen.

Wenn die Funktion fopen() aus dem einen oder anderen Grund (es gibt keine Datei an der angegebenen Adresse, der Zugriff darauf ist verweigert) die Datei nicht öffnen kann, gibt sie NULL zurück. In realen Programmen behandeln sie fast immer einen Fehler beim Öffnen einer Datei im if-Zweig, wir werden dies jedoch weiter weglassen.

Die Funktionsdeklaration fopen() ist in der Header-Datei stdio.h enthalten und muss daher einbezogen werden. Auch in stdio.h ist der Strukturtyp FILE deklariert.

Nachdem die Arbeit mit einer Datei abgeschlossen ist, ist es üblich, sie zu schließen, um den Puffer von Daten zu befreien und aus anderen Gründen. Dies ist besonders wichtig, wenn das Programm nach der Arbeit mit der Datei weiterläuft. Das Unterbrechen der Verbindung zwischen einer externen Datei und einem Zeiger darauf vom Programm erfolgt mit der Funktion fclose(). Als Parameter wird ihr ein Zeiger auf die Datei übergeben:
fclose(meineDatei);

Im Programm können mehrere Dateien geöffnet werden. In diesem Fall muss jeder Datei ein eigener Dateizeiger zugeordnet werden. Wenn das Programm jedoch zunächst mit einer Datei arbeitet und diese dann schließt, kann der Zeiger zum Öffnen einer zweiten Datei verwendet werden.

Lesen aus und Schreiben in eine Textdatei

fscanf()

Die Funktion fscanf() hat eine ähnliche Bedeutung wie die Funktion scanf(), stellt jedoch im Gegensatz zu dieser eine formatierte Eingabe aus einer Datei anstelle einer Standardeingabe bereit. Die Funktion fscanf() benötigt Parameter: Dateizeiger, Formatzeichenfolge, Adressen von Speicherbereichen zum Schreiben von Daten:
fscanf(myfile, "%s%d", str, &a);

Gibt die Anzahl der erfolgreich gelesenen Daten oder EOF zurück. Leerzeichen und Zeilenumbrüche werden als Datentrennzeichen gezählt.

Nehmen wir an, wir haben eine Datei mit der folgenden Beschreibung von Objekten:

Äpfel 10 23,4 Bananen 5 25,0 Brot 1 10,3

#enthalten main () ( FILE * file; struct food ( char name[ 20 ] ; unsigned qty; float price; ); struct food shop[ 10 ] ; char i= 0 ; file = fopen ("fscanf.txt" , "r" ); while (fscanf (file, "%s%u%f" , shop[ i].name , & (shop[ i].qty ) , & (shop[ i].price ) ) != EOF) ( printf ("%s %u %.2f \N", shop[ i].name, shop[ i].qty, shop[ i].price); i++; ) )

In diesem Fall werden eine Struktur und ein Array von Strukturen deklariert. Jede Zeile aus der Datei entspricht einem Element des Arrays; Ein Array-Element ist eine Struktur, die eine Zeichenfolge und zwei numerische Felder enthält. Die Schleife liest eine Zeile pro Iteration. Wenn das Ende der Datei erreicht ist, gibt fscanf() EOF zurück und die Schleife endet.

fgets()

Die Funktion fgets() ähnelt der Funktion gets() und führt zeilenweise Eingaben aus einer Datei aus. Ein Aufruf von fgets() liest eine Zeile. In diesem Fall können Sie nicht die gesamte Zeile lesen, sondern nur einen Teil davon von Anfang an. fgets()-Parameter sehen so aus:
fgets (character_array, number_of_characters_read, pointer_to_file)

Zum Beispiel:
fgets(str, 50, myfile)

Dieser Funktionsaufruf liest aus der mit dem myfile-Zeiger verknüpften Datei eine vollständige Textzeile, wenn ihre Länge weniger als 50 Zeichen beträgt, einschließlich des Zeichens „\n“, das die Funktion ebenfalls in einem Array speichert. Das letzte (50.) Element des str-Arrays ist das von fgets() hinzugefügte Zeichen „\0“. Wenn die Zeichenfolge länger ist, liest die Funktion 49 Zeichen und schreibt am Ende „\0“. In diesem Fall ist „\n“ nicht in der Lesezeile enthalten.

#enthalten #define N 80 main () ( FILE * file; char arr[ N] ; file = fopen ("fscanf.txt" , "r" ) ; while (fgets (arr, N, file) != NULL) printf (" %s" , arr) ; printf (" \N"); fclose(Datei); )

In diesem Programm werden die Daten im Gegensatz zum vorherigen zeilenweise in das arr-Array eingelesen. Beim Lesen der nächsten Zeile geht die vorherige verloren. Die Funktion fgets() gibt NULL zurück, wenn sie die nächste Zeile nicht lesen kann.

getc() oder fgetc()

Mit der Funktion getc() oder fgetc() (beide funktionieren) können Sie das nächste einzelne Zeichen aus einer Datei abrufen.

while ((arr[ i] = fgetc (file) ) != EOF) ( if (arr[ i] == " \N") (arr[i] = " \0 " ; printf("%s \N", arr) ; ich = 0 ; ) sonst i++; )arr[i] = " \0 " ; printf("%s \N", arr) ;

Der Beispielcode zeigt Daten aus einer Datei auf dem Bildschirm an.

Schreiben in eine Textdatei

Genau wie die Eingabe kann auch die Ausgabe in eine Datei unterschiedlich sein.

  • Formatierte Ausgabe. Funktion fprintf (file_index, format_string, variables) .
  • Post-by-Line-Ausgabe. Funktion fputs(string, file_pointer) .
  • Zeichenweise Ausgabe. Funktion fputc() oder putc(symbol, file_pointer) .

Nachfolgend finden Sie Codebeispiele, die drei Methoden zum Ausgeben von Daten in eine Datei verwenden.

Felder einer Struktur in jede Zeile der Datei schreiben:

file = fopen ("fprintf.txt" , "w" ); while (scanf ("%s%u%f" , shop[ i].name , & (shop[ i].qty ) , & (shop[ i].price ) ) != EOF) ( fprintf (file, " %s %u %.2f \N", shop[ i].name, shop[ i].qty, shop[ i].price); i++; )

Zeilenweise Ausgabe in eine Datei (fputs() setzt im Gegensatz zu puts() selbst kein „\n“ am Ende der Zeile):

while (gets (arr) != NULL) ( fputs (arr, file); fputs (" \N", Datei); )

Beispiel für eine zeichenweise Ausgabe:

while ((i = getchar () ) != EOF) putc (i, file) ;

Lesen und Schreiben in eine Binärdatei

Sie können mit einer Datei nicht als Folge von Zeichen, sondern als Folge von Bytes arbeiten. Eine andere Arbeit mit Nicht-Textdateien ist prinzipiell nicht möglich. Sie können auf diese Weise jedoch Textdateien lesen und schreiben. Der Vorteil dieser Zugriffsmethode auf eine Datei liegt in der Lese-/Schreibgeschwindigkeit: Mit einem Zugriff kann ein erheblicher Informationsblock gelesen/geschrieben werden.

Beim Öffnen einer Datei für den Binärzugriff ist der zweite Parameter von fopen() die Zeichenfolge „rb“ oder „wb“.

Das Thema der Arbeit mit Binärdateien ist recht komplex und erfordert eine separate Lektion, um es zu studieren. Hier werden nur die Funktionen des Lesens und Schreibens in eine Datei, die als Bytestream betrachtet wird, erwähnt.

Die Funktionen fread() und fwrite() verwenden als Parameter:

  1. Adresse des Speicherbereichs, in den Daten geschrieben oder gelesen werden,
  2. die Größe eines gegebenen Typs,
  3. die gelesene Datenmenge der angegebenen Größe,
  4. Dateiindex.

Diese Funktionen geben die Anzahl der erfolgreich gelesenen oder geschriebenen Daten zurück. Diese. Sie können das Lesen von 50 Datenelementen „anordnen“, erhalten aber nur 10. Es wird kein Fehler angezeigt.

Ein Beispiel für die Verwendung der Funktionen fread() und fwrite():

#enthalten #enthalten main () ( FILE * file; char Shelf1[ 50 ], Shelf2[ 100 ] ; int n, m; file = fopen ("shelf1.txt" , "rb" ) ; n= fread (shelf1, sizeof (char ) , 50 , Datei) ; fclose (Datei) ; file = fopen ("shelf2.txt" , "rb" ); m= fread (shelf2, sizeof (char ) , 50 , Datei) ; fclose (Datei) ; Shelf1[ n] = " \0 " ; Shelf2[m] = " \N"; Shelf2[ m+ 1 ] = " \0 " ; file = fopen ("shop.txt" , "wb" ); fwrite (strcat (shelf2, Shelf1) , sizeof (char ) , n+ m, file) ; fclose(Datei); )

Hier wird versucht, 50 Zeichen aus der ersten Datei zu lesen. n speichert die Anzahl der tatsächlich gelesenen Zeichen. Der Wert von n kann 50 oder weniger betragen. Die Daten werden in einer Zeile platziert. Das Gleiche passiert mit der zweiten Datei. Als nächstes wird die erste Zeile an die zweite angehängt und die Daten werden in die dritte Datei übertragen.

Probleme lösen

  1. Schreiben Sie ein Programm, das den Benutzer nach dem Namen (Adresse) einer Textdatei fragt, diese dann öffnet und die Anzahl der darin enthaltenen Zeichen und Zeilen zählt.
  2. Schreiben Sie ein Programm, das Daten in eine Datei schreibt, die von einer anderen Datei empfangen und vor dem Schreiben auf irgendeine Weise geändert wurden. Jede aus einer Datei erhaltene Datenzeile muss in eine Struktur passen.

Letzte Aktualisierung: 31.10.2015

Es gibt zwei Klassen, die für die Arbeit mit Verzeichnissen im System.IO-Namespace konzipiert sind: Directory und DirectoryInfo.

Verzeichnisklasse

Die Directory-Klasse stellt eine Reihe statischer Methoden zum Verwalten von Verzeichnissen bereit. Einige dieser Methoden:

    CreateDirectory(path) : erstellt ein Verzeichnis im angegebenen Pfad

    Löschen(Pfad): löscht das Verzeichnis im angegebenen Pfad

    Exists(path) : Bestimmt, ob das Verzeichnis im angegebenen Pfad existiert. Wenn vorhanden, wird „true“ zurückgegeben, wenn nicht vorhanden, wird „false“ zurückgegeben

    GetDirectories(path) : Ruft eine Liste der Verzeichnisse im Verzeichnispfad ab

    GetFiles(path) : Ruft eine Liste der Dateien im Verzeichnispfad ab

    Move(sourceDirName, destDirName): verschiebt ein Verzeichnis

    GetParent(path) : Ruft das übergeordnete Verzeichnis ab

DirectoryInfo-Klasse

Diese Klasse bietet Funktionen zum Erstellen, Löschen, Verschieben und für andere Verzeichnisvorgänge. In vielerlei Hinsicht ähnelt es Directory. Einige seiner Eigenschaften und Methoden:

    Create(): Erstellt ein Verzeichnis

    CreateSubdirectory(path) : Erstellt ein Unterverzeichnis im angegebenen Pfad

    Delete(): löscht ein Verzeichnis

    Exists-Eigenschaft: Bestimmt, ob ein Verzeichnis existiert

    GetDirectories(): Ruft eine Liste von Verzeichnissen ab

    GetFiles(): Ruft eine Liste von Dateien ab

    MoveTo(destDirName) : Verschiebt ein Verzeichnis

    Parent-Eigenschaft: Abrufen des übergeordneten Verzeichnisses

    Root-Eigenschaft: Ruft das Root-Verzeichnis ab

Schauen wir uns Beispiele für die Verwendung dieser Klassen an

Abrufen einer Liste von Dateien und Unterverzeichnissen

string dirName = "C:\\"; if (Directory.Exists(dirName)) ( Console.WriteLine("Subdirectories:"); string dirs = Directory.GetDirectories(dirName); foreach (string s in dirs) ( Console.WriteLine(s); ) Console.WriteLine( ); Console.WriteLine("Files:"); string files = Directory.GetFiles(dirName); foreach (string s in files) ( Console.WriteLine(s); ) )

Bitte beachten Sie die Verwendung von Schrägstrichen in Dateinamen. Entweder verwenden wir einen doppelten Schrägstrich: „C:\\“ oder einen einzelnen Schrägstrich, setzen dann aber das @-Zeichen vor den gesamten Pfad: @„C:\Programme“

Erstellen eines Verzeichnisses

string path = @"C:\SomeDir"; string subpath = @"program\avalon"; DirectoryInfo dirInfo = new DirectoryInfo(path); if (!dirInfo.Exists) ( dirInfo.Create(); ) dirInfo.CreateSubdirectory(subpath);

Zuerst prüfen wir, ob ein solches Verzeichnis existiert, denn wenn es existiert, ist es nicht möglich, es zu erstellen, und die Anwendung gibt einen Fehler aus. Als Ergebnis erhalten wir den folgenden Pfad: „C:\SomeDir\program\avalon“

Verzeichnisinformationen abrufen

string dirName = "C:\\Programme"; DirectoryInfo dirInfo = new DirectoryInfo(dirName); Console.WriteLine($"Verzeichnisname: (dirInfo.Name)"); Console.WriteLine($"Vollständiger Verzeichnisname: (dirInfo.FullName)"); Console.WriteLine($"Zeitpunkt der Verzeichniserstellung: (dirInfo.CreationTime)"); Console.WriteLine($"Stammverzeichnis: (dirInfo.Root)");

Ein Verzeichnis entfernen

Wenn wir die Methode „Delete“ einfach auf einen nicht leeren Ordner anwenden, der einige Dateien oder Unterverzeichnisse enthält, gibt die Anwendung einen Fehler aus. Daher müssen wir einen zusätzlichen booleschen Typparameter an die Methode „Delete“ übergeben, der angibt, dass der Ordner mit seinem gesamten Inhalt gelöscht werden soll:

String dirName = @"C:\SomeFolder"; try ( DirectoryInfo dirInfo = new DirectoryInfo(dirName); dirInfo.Delete(true); Console.WriteLine("Verzeichnis gelöscht"); ) Catch (Exception ex) ( Console.WriteLine(ex.Message); )

String dirName = @"C:\SomeFolder"; Directory.Delete(dirName, true);

Verschieben eines Verzeichnisses

string oldPath = @"C:\SomeFolder"; string newPath = @"C:\SomeDir"; DirectoryInfo dirInfo = new DirectoryInfo(oldPath); if (dirInfo.Exists && Directory.Exists(newPath) == false) ( dirInfo.MoveTo(newPath); )

Beim Verschieben müssen wir berücksichtigen, dass das neue Verzeichnis, in das wir den gesamten Inhalt des alten Verzeichnisses verschieben möchten, nicht existieren sollte.

gastroguru 2017