Dateioperationen in C-Sprache

Vorwort

Warum brauchen wir Dateioperationen? Wenn wir Code schreiben, wird der eingegebene Inhalt im Speicher gespeichert, und wenn das Programm endet oder der Strom ausgeschaltet wird, wird der Inhalt ebenfalls zerstört. Auf diese Weise können Informationen nicht gespeichert werden, was das Problem der Datenpersistenz mit sich bringt. Unsere allgemeinen Datenpersistenzmethoden umfassen das Speichern von Daten in Festplattendateien, das Speichern von Daten in Datenbanken usw. Mithilfe von Dateien können wir Daten direkt auf der Festplatte des Computers speichern und so Datenpersistenz erreichen.

Die Beziehung zwischen Speicher und Dateien wird im folgenden Bild erläutert.
Fügen Sie hier eine Bildbeschreibung ein
Lass uns Dateioperationen lernen

1.Was ist eine Datei?

Die Dateien auf der Festplatte sind Dateien.
Bei der Programmierung sprechen wir jedoch im Allgemeinen von zwei Arten von Dateien: Programmdateien und Datendateien (klassifiziert aus der Perspektive der Dateifunktion).
1.1 Programmdateien

包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境
后缀为.exe)。

1.2 Datendateien

文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,
或者输出内容的文件。

Bevor wir Dateioperationen lernen, geben wir alle über die Tastatur ein und geben sie dann auf dem Bildschirm aus. Dies ermöglicht keine Datenpersistenz. Jetzt können wir die Daten auf die Festplatte schreiben und sie dann auf der Festplatte speichern . Daten werden in das Programm eingegeben. Dadurch kann auch Datenpersistenz erreicht werden.
1.3 Dateiname
Eine Datei muss eine eindeutige Dateiidentifikation haben, um die Identifizierung und Referenzierung durch den Benutzer zu erleichtern.
Der Dateiname besteht aus 3 Teilen: Dateipfad + Dateiname Stamm + Dateisuffix

D:\bite study code\task\task_10_12\text.c
//文件路径:D:\bite study code\task\task_10_12
//文件主干:text
//文件后缀:.c

Der Einfachheit halber nennen wir die Dateikennung den Dateinamen

2. Dateien öffnen und schließen

2.1 Dateizeiger
Im gepufferten Dateisystem ist das Schlüsselkonzept der „Dateitypzeiger“, der als „Dateizeiger“ bezeichnet wird.
Jede verwendete Datei öffnet einen entsprechenden Dateiinformationsbereich im Speicher, in dem die relevanten Informationen der Datei gespeichert werden (z. B. der Name der Datei
). , Dateistatus und aktueller Speicherort der Datei usw.). Diese Informationen werden in einer Strukturvariablen gespeichert. Der Strukturtyp wird vom System
deklariert und FILE genannt.
Beispiel:
im von der VS2013-Kompilierung bereitgestellten Standard Umgebung Die .h-Header-Datei hat die folgende Dateitypdeklaration:

struct _iobuf {
    
    
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
       };
typedef struct _iobuf FILE;

In verschiedenen Compilern ist auch der Inhalt der FILE-Struktur unterschiedlich.
Immer wenn der Benutzer eine Datei öffnet, erstellt das Betriebssystem die Variablen der FILE-Struktur selbst und füllt den Inhalt der Struktur aus. Der Benutzer muss sich darüber keine Gedanken machen.
Wenn wir etwas in die Datei schreiben oder etwas in die Datei abrufen möchten, benötigen wir nur eine Adresse, an der wir den Dateiinformationsbereich finden können, und können dann über den Dateiinformationsbereich auf diese Datei zugreifen .
Wir erstellen eine Adresse (FILE*-Zeigervariable) wie folgt:

FILE* pf;//文件指针变量

definiert pf als Zeigervariable, die auf Daten vom Typ FILE zeigt. Sie können pf auf den Dateiinformationsbereich einer bestimmten Datei verweisen lassen (es handelt sich um eine Strukturvariable). Auf die Datei kann über die Informationen im Dateiinformationsbereich zugegriffen werden. Mit anderen Worten: Die zugehörige Datei kann über die Dateizeigervariable gefunden werden.
Zum Beispiel:
Fügen Sie hier eine Bildbeschreibung ein
2.2 Öffnen und Schließen von Dateien
Die Datei sollte vor dem Lesen und Schreiben geöffnet und geöffnet werden nach Gebrauch. Schließen Sie die Datei.
Beim Schreiben eines Programms wird beim Öffnen einer Datei eine FILE*-Zeigervariable zurückgegeben, die auf die Datei zeigt, was dem Einrichten eines
Zeigers und einer Datei entspricht Beziehung.
ANSIC schreibt vor, dass die Funktion fopen zum Öffnen der Datei und fclose zum Schließen der Datei verwendet wird.

//打开文件
FILE * fopen ( const char * filename, const char * mode );
//关闭文件
int fclose ( FILE * stream );

Öffnen Sie wie folgt:
Fügen Sie hier eine Bildbeschreibung ein
Beispielcode:

#include <stdio.h>
int main ()
{
    
    
  FILE * pFile;
  //打开文件
  pFile = fopen ("myfile.txt","w");
  //文件操作
  if (pFile!=NULL)
 {
    
    
    fputs ("fopen example",pFile);
    //关闭文件
    fclose (pFile);
 }
  return 0;
  }

Lassen Sie uns über ein Pfadproblem sprechen. Beim Öffnen einer Datei bezieht sich const char * filename auf den Namen der Datei. Standardmäßig befindet sich die Datei im aktuellen Pfad des Programms. Wenn Sie diese Datei auf dem ablegen Obere Ebene oder höher. Wenn wir auf diese Datei zugreifen, wird angezeigt, dass die Datei nicht gefunden werden kann.
Pfad:
1. Relativer Pfad

.\\当前路径
..\\上一级路径

Warum \ anstelle von \ verwenden, weil \ Escape im Programm bedeutet
2. Absoluter Pfad

D:\\bite study code\\task\\task_10_11\\task_10_11\\data.txt   绝对路径

Aktuelle Spalte des Codes:

#include<stdio.h>
int main()
{
    
    
	//打开文件
	/*FILE* pf=fopen("data.txt", "w");*/
	//相对路径
	//  .\\指当前路径  
	//   ..\\指上一个路径


	/*FILE* pf = fopen(".\\..\\data.txt", "r");*///指当前路径的上一个路径   

	/*FILE* pf = fopen("..\\..\\data.txt", "r");*///指当前路径的上一个路径的上一个路径


	//绝对路径

	FILE* pf = fopen("D:\\bite study code\\task\\task_10_11\\task_10_11\\data.txt", "r");//这个就是从根找,就是绝对路径

	if (pf == NULL)
	{
    
    
		perror("fopen");
		return;
	}
	//写文件



	//关闭文件
	fclose(pf);
	pf = NULL;

	return 0;
}

3. Sequentielles Lesen und Schreiben von Dateien

Fügen Sie hier eine Bildbeschreibung ein
Wir unterteilen es in eine Kategorie:
Zeichenklasse: Zeicheneingabefunktion (fgetc), Zeichenausgabefunktion (fputc)
Textzeile (Zeichenfolge ) : Textzeilen-Eingabefunktion (fgets) Textausgabefunktion (fputs)
Formatierung (Ganzzahl, Gleitkomma): Formatierte Eingabefunktion (fscanf) Formatierte Ausgabefunktion (fprintf) a>
Binär: Binärer Eingang (fread) Binärer Ausgang (fwrite)

Bevor wir diese Funktionen vorstellen, sprechen wir zunächst über das Konzept des Streams. Das Konzept des Streams selbst ist eine äußerst abstrakte Sache. Alle Streams sind in zwei Typen unterteilt, einer ist der Standard-Stream und der andere ist die Datei Stream. .
Standard-Stream:
1. Standard-Eingabestream: stdin (Eingabe über die Tastatur)
2. Standard-Ausgabestream: stdout( Drucken auf dem Bildschirm)
Dateistream:
1. Dateieingabestream: Lesen Sie den Inhalt der Datei und geben Sie ihn in den Speicher ein
2. Dateiausgabestream: Ausgabe in eine Datei über ein In-Memory-Programm

Zeichenklasse:
Zeichenausgabefunktion (fputc)

int fputc ( int character, FILE * stream );

int-Zeichen: Das Zeichen, das Sie aus dem Speicher in die Datei ausgeben müssen. Das Zeichen hier muss ganzzahlig heraufgestuft und dann intern in ein vorzeichenloses Zeichen konvertiert werden.
FILE * Stream: Zeiger Zeiger, der das FILE-Objekt des Ausgabestreams identifiziert (wird tatsächlich an die Adresse ausgegeben, die auf den Dateiinformationsbereich zeigt, und dann den Inhalt über die Informationen im Dateiinformationsbereich in die Datei einfügen)
Das Rückgabetyp ist: int
Wenn die Rückgabe erfolgreich ist, ist der zurückgegebene Wert der ASCII-Codewert des Zeichens.
Wenn die Rückgabe fehlschlägt, ist der zurückgegebene Wert EOF (-1) zur Bestätigung des oben zurückgegebenen Typs.
Code-Implementierung:

#include<stdio.h>
int main()
{
    
    
	//打开文件
	FILE* pf = fopen("data.txt", "w");
	//判断是否打开成功
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//写文件
	fputc('a', pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

In der Datei angezeigt:
Fügen Sie hier eine Bildbeschreibung ein
Ich muss jetzt 26 Buchstaben drucken:

int main()
{
    
    
	//打开文件
	FILE* pf = fopen("data.txt", "w");
	//判断是否打开成功
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//写文件
	char ch;
	for (ch = 'a'; ch <= 'z'; ch++)
	{
    
    
		fputc(ch, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

In der Datei angezeigt:
Fügen Sie hier eine Bildbeschreibung ein
Zeichenausgabefunktion (fgetc)

int fgetc ( FILE * stream )

FILE * Stream: Zeiger auf das FILE-Objekt, das den Eingabestream identifiziert (gibt den Inhalt der Datei in den Speicher ein)
Rückgabetyp: int
Rückgabewert: Wenn die Rückgabe erfolgreich ist, wird das zurückgegebene Zeichen ganzzahlig erhöht und dann als ASCII-Codewert an den Speicher zurückgegeben.
Wenn die Rückgabe fehlschlägt, EOF zurückgeben
Code-Implementierung:

int main()
{
    
    
	//打开文件
	FILE* pf = fopen("data.txt", "r");
	//判断是否打开成功
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//读文件
	int ch=fgetc(pf);
	printf("%c", ch);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 

Wir drucken auf dem Bildschirm:
Fügen Sie hier eine Bildbeschreibung ein
Textklasse:
Textausgabefunktion (fputs)

int fputs ( const char * str, FILE * stream );

const char * str: Die auszugebende Zeichenfolge
FILE * stream: Zeiger auf das FILE-Objekt, das den Ausgabestream identifiziert
Rückgabetyp: int
Rückgabewert: Gibt bei Erfolg einen nicht negativen Wert zurück.
Gibt EOF zurück, wenn fehlgeschlagen.
Code-Implementierung:

int main()
{
    
    
	//打开文件
	FILE* pf = fopen("data.txt", "w");
	//判断是否打开成功
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//写文件
	fputs("abcdefg", pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

In der Datei angezeigt:
Fügen Sie hier eine Bildbeschreibung ein
Texteingabefunktion (fgets)

char * fgets ( char * str, int num, FILE * stream );

char * str: Zeiger auf das Zeichenarray, das in das Ziel kopiert werden muss
int num: Die maximale Anzahl der in str kopierten Zeichen (das Kopieren wird beendet, wenn ein Zeilenumbruchzeichen angezeigt wird wird angetroffen, vorausgesetzt, dass, wenn das Ziel Das maximale Zeichenarray beträgt 100, aber nur 99 Zeichen kopiert werden können)
FILE * Stream: Zeiger auf das FILE-Objekt, das den Eingabestream identifiziert.
Rückgabetyp: char*
Rückgabewert: Bei erfolgreicher Rückgabe wird die erste Adresse des str-Arrays zurückgegeben.
Wenn die Rückgabe fehlschlägt, wird ein Nullzeiger zurückgegeben. (NULL)
Code-Implementierung:

int main()
{
    
    
	char arr[5] = {
    
     0 };
	//打开文件
	FILE* pf = fopen("data.txt", "r");
	//判断是否打开成功
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//读文件
	fgets(arr, 5, pf);
	printf("%s", arr);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

Auf dem Bildschirm drucken:
Fügen Sie hier eine Bildbeschreibung ein
Wenn Sie der Datei ein Zeilenumbruchzeichen hinzufügen:
Fügen Sie hier eine Bildbeschreibung ein
Wenn Sie auf ein Leerzeichen stoßen, können Sie das Leerzeichen trotzdem drucken :
Fügen Sie hier eine Bildbeschreibung ein

Formatierung:
Ausgabefunktion formatieren (fprintf)

int fprintf ( FILE * stream, const char * format, ... );

FILE * stream: Zeiger auf das FILE-Objekt, das den Ausgabestream identifiziert.
const char * Format: Vergleichen Sie die Beschreibung der printf-Funktion
Angenommen, Sie möchten ganzzahlige Daten ausgeben:
printf-Funktion printf( "%d",a);
fprintf function fprintf( FILE * stream, "%d", a);
Rückgabetyp: int Code-Implementierung: Wenn die Rückgabe fehlschlägt, wird eine negative Zahl zurückgegeben.
Rückgabewert: Bei Erfolg wird die Gesamtzahl der geschriebenen Zeichen zurückgegeben.

struct stu
{
    
    
	char name[20];
	int age;
	float hight;
};
int main()
{
    
    
	 struct stu s = {
    
     "zhangsan",20,175.00 };
	 //打开文件
	 FILE* pf=fopen("data.txt", "w");
	 if (pf == NULL)
	 {
    
    
		 perror("fopen");
	 }
	 //写文件
	 fprintf(pf, "%s-%d-%f", s.name, s.age, s.hight);
	 //关闭文件
	 fclose(pf);
	 pf = NULL;
	return 0;
}

In der Datei angezeigt:
Fügen Sie hier eine Bildbeschreibung ein
Formateingabefunktion (fscanf)

int fscanf ( FILE * stream, const char * format, ... );

FILE * Stream: Zeiger auf ein FILE-Objekt, das den Eingabestream identifiziert, aus dem Daten gelesen werden sollen
Rückgabetyp: int
Code-Implementierung: < /span>

struct stu
{
    
    
	int age;
	float hight;
	char name[20];
};
int main()
{
    
    
	struct stu s = {
    
    0};
	//打开文件
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//读文件
	fscanf(pf, "%d-%f-%s", &(s.age), &(s.hight),s.name);
	printf("%s-%d-%f", s.name, s.age, s.hight);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

Auf dem Bildschirm drucken:
Fügen Sie hier eine Bildbeschreibung ein
Binärfunktion:
Binärausgabefunktion (fwrite)

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

const void * ptr: Zeigt auf die Adresse des zu schreibenden Elementarrays
size_t size: Die Größe jedes Elements, das kopiert werden muss (in Bytes)Code-Implementierung: FILE * stream: Zeiger auf das FILE-Objekt des angegebenen Ausgabestreams.
size_t count: Die Anzahl der zu kopierenden Elemente

int main()
{
    
    
	int arr[10] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	//打开文件
	FILE* pwrite = fopen("data.txt", "wb");
	if (pwrite == NULL)
	{
    
    
		perror("fopen");
	}
	//读文件
	fwrite(arr, sizeof(arr[0]), sizeof(arr) / sizeof(arr[0]), pwrite);
	//关闭文件
	fclose(pwrite);
	pwrite = NULL;
	return 0;
}

Schauen Sie unter der Datei nach:
Fügen Sie hier eine Bildbeschreibung ein
ist eine Zeichenfolge unverständlicher verstümmelter Zeichen, da sie in binärer Form in der Datei gespeichert ist, obwohl wir sie in der Datei nicht verstehen können, aber sie kann in den Speicher umgewandelt und auf dem Bildschirm ausgedruckt werden. Um es in den Speicher umzuwandeln, benötigen Sie eine binäre Eingabefunktion (fread). Als nächstes lernen wir diese Funktion.

Binäre Eingabefunktion (fread)

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

void * ptr: Zeigt auf die Adresse, die in das Elementarray kopiert werden soll
size_t size: Die Größe jedes zu kopierenden Elements (in Bytes)
size_t count: Die Anzahl der zu kopierenden Elemente
FILE * stream: Zeiger auf das FILE-Objekt des angegebenen Eingabestreams.
Rückgabetyp: size_t
Code-Implementierung:

int main()
{
    
    
	int arr[10] = {
    
    0};
	//打开文件
	FILE* fwrite=fopen("data.txt", "rb");
	if (fwrite == NULL)
	{
    
    
		perror("fopen");
	}
	//读文件
	fread(arr, sizeof(arr[0]), sizeof(arr) / sizeof(arr[0]), fwrite);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
	//关闭文件
	fclose(fwrite);
	fwrite = NULL;
	return 0;
}

Auf dem Bildschirm drucken:
Fügen Sie hier eine Bildbeschreibung ein

4 Zufälliges Lesen und Schreiben von Dateien

4.1fseek-Funktion

int fseek ( FILE * stream, long int offset, int origin );

FILE * stream: Zeiger auf das FILE-Objekt, das den Stream identifiziert
long int offset: Offset
int origin: Die Position des Dateicursors< /span>Codebeispiel: Um Diesmal: Der Dateicursor ist nicht der Dateizeiger. Der Dateizeiger bewegt sich nicht. Es ist eine ziemliche Orientierungshilfe. Der Dateicursor bewegt sich, und wenn auf den Inhalt zugegriffen wird, zeigt der Cursor dorthin. SEEK_END Ende der Datei SEEK_CUR Aktuelle Position des Dateicursors
SEEK_SET Anfang der Datei



#include<stdio.h>
int main()
{
    
    
	char arr[10] = {
    
     0 };
	//打开文件
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//随机访问文件的内容
	fseek(pf, 2, SEEK_SET);
	//读文件
	fgets(arr, 10, pf);
	printf("%s", arr);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

Die festgelegte Bedingung besteht darin, den Anfangsoffset der Datei am Dateicursor auf 2 zu setzen.
Auf dem Bildschirm ausgeben:
Fügen Sie hier eine Bildbeschreibung ein
4.2fetll (return zur Datei Der Offset des Zeigers relativ zur Startposition)

long int ftell ( FILE * stream );

Beispiel:

#include <stdio.h>
int main ()
{
    
    
  FILE * pFile;
  long size;
  pFile = fopen ("myfile.txt","rb");
  if (pFile==NULL) perror ("Error opening file");
  else
 {
    
    
    fseek (pFile, 0, SEEK_END);   // non-portable
    size=ftell (pFile);
    fclose (pFile);
    printf ("Size of myfile.txt: %ld bytes.\n",size);
 }
  return 0;
}

4.3rewind (setzen Sie die Position des Dateizeigers auf die Startposition der Datei zurück)

void rewind ( FILE * stream );

Beispiel:

#include <stdio.h>
int main ()
{
    
    
  int n;
  FILE * pFile;
  char buffer [27];
  pFile = fopen ("myfile.txt","w+");
  for ( n='A' ; n<='Z' ; n++)
    fputc ( n, pFile);
  rewind (pFile);
  fread (buffer,1,26,pFile);
  fclose (pFile);
  buffer[26]='\0';
  puts (buffer);
    return 0;
}

5. Textdateien und Binärdateien

Je nachdem, wie die Daten organisiert sind, werden Datendateien als Textdateien oder Binärdateien bezeichnet.
Die Daten werden in binärer Form im Speicher abgelegt. Werden sie ohne Konvertierung in den externen Speicher ausgegeben, handelt es sich um eine Binärdatei.
Wenn es im ASCII-Code auf einem externen Speicher gespeichert werden soll, muss es vor der Speicherung konvertiert werden. In Form von ASCII-Zeichen gespeicherte Dateien sind Textdateien.

6. Bestimmung des Endes des Dateilesens

6.1 Falsch verwendetes feof
Denken Sie daran: Während des Dateilesevorgangs kann der Rückgabewert der feof-Funktion nicht verwendet werden, um direkt zu bestimmen, ob die Datei beendet ist.
Stattdessen wird es verwendet, wenn das Lesen der Datei endet, um zu bestimmen, ob das Lesen fehlschlägt oder das Ende der Datei erreicht ist.

  1. Ob das Lesen der Textdatei abgeschlossen ist, bestimmen Sie, ob der Rückgabewert EOF (fgetc) oder NULL (fgets) ist
    Beispiel:
    fgetc bestimmt, ob es EOF ist.
    fgets bestimmt, ob der Rückgabewert NULL ist.
  2. Beurteilen Sie das Ende des Lesens der Binärdatei und beurteilen Sie, ob der Rückgabewert kleiner als die tatsächlich zu lesende Zahl ist.
    Beispiel:
    fread ermittelt, ob der Rückgabewert kleiner als die tatsächlich zu lesende Zahl ist.
    ####### 7. Datei-Cache-Bereich

7. Datei-Cache-Bereich

Der ANSIC-Standard verwendet ein „Pufferdateisystem“ zur Verarbeitung von Datendateien. Das sogenannte Pufferdateisystem bedeutet, dass das System automatisch einen „Dateipuffer“ im Speicher für jede im Programm verwendete Datei öffnet . Die vom Speicher an die Festplatte ausgegebenen Daten werden zuerst an den Puffer im Speicher gesendet und dann zusammen an die Festplatte gesendet, nachdem der Puffer gefüllt ist. Wenn Daten von der Festplatte zum Computer gelesen werden, werden die Daten aus der Festplattendatei gelesen und in den Speicherpuffer eingegeben (der Puffer ist gefüllt), und dann werden die Daten vom Puffer an den Programmdatenbereich (Programmvariablen, usw.) nacheinander. Die Größe des Puffers wird durch das C-Kompilierungssystem bestimmt.
Fügen Sie hier eine Bildbeschreibung ein
Eine Schlussfolgerung kann hier gezogen werden:
Aufgrund der Existenz des Puffers muss die C-Sprache, wenn sie eine Datei bearbeitet, den Puffer aktualisieren oder beenden Dateivorgang. Beim Schließen der Datei.
Andernfalls kann es zu Problemen beim Lesen und Schreiben von Dateien kommen.

Ende dieses Kapitels…

Supongo que te gusta

Origin blog.csdn.net/HD_13/article/details/133807993
Recomendado
Clasificación