[C-Sprache] Dateioperation (sehr ausführliche Erklärung)

1. Was ist ein Dokument?

Computerdateien sind eine Art von Dateien. Im Gegensatz zu gewöhnlichen Dateiträgern handelt es sich bei dieser Art von Dateien um eine Sammlung von Informationen, die auf einem Computer mit einer Festplatte als Träger gespeichert sind.
Beim Programmieren sprechen wir im Allgemeinen von zwei Arten von Dateien: Programmdateien und Datendateien.

Programmdateien: einschließlich Quellprogrammdateien (Suffix .c), Zieldateien (Windows-Umgebungssuffix .obj), ausführbare Programme (Windows-Umgebungssuffix .exe).
Datendatei: Der Inhalt der Datei ist nicht unbedingt das Programm, sondern die Daten, die beim Ausführen des Programms gelesen und geschrieben werden, z. B. die Datei, aus der das Programm Daten lesen muss, oder die Datei, die den Inhalt ausgibt.

Der Inhalt dieses Artikels richtet sich an Datendateien . Die Eingabe und Ausgabe der zuvor gelernten Daten basiert auf dem Terminal, dh die Daten werden über die Tastatur des Terminals eingegeben und die laufenden Ergebnisse werden auf dem Monitor angezeigt. Die Ausgabe und Eingabe von Daten kann jedoch auch zwischen dem Speicher und der Datei übertragen werden, was auch das in diesem Artikel behandelte Objekt ist. Die Ausgabe der Daten wird aus dem Speicher in die Datei geschrieben, und die Eingabe der Daten erfolgt Aus der Datei in den Speicher lesen. go .

1. Dateiname

Eine Datei muss eine eindeutige Dateikennung haben, und der Dateiname ist auch die Kennung der Existenz der Datei. Das Betriebssystem steuert und verwaltet sie entsprechend dem Dateinamen. Der Dateiname dient zur Identifizierung und Referenz des Benutzers.
Der Dateiname besteht aus 3 Teilen: Dateipfad + Dateiname Stamm + Dateisuffix.
Beispiel:c:\code\test\test.txt

Dateipfad: c:\code\test\
Dateiname Stamm: test
Dateisuffix:.txt

2. Dateityp

Je nachdem, wie die Daten organisiert sind, können Datendateien als Textdateien oder Binärdateien klassifiziert werden.
Die Daten werden in binärer Form im internen Speicher gespeichert. Wenn sie ohne Konvertierung an den externen Speicher ausgegeben werden, handelt es sich um eine Binärdatei . Wenn sie in Form von ASCII-Code im externen Speicher gespeichert werden müssen, handelt es sich um eine Binärdatei muss vor der Lagerung konvertiert werden. Eine in Form von ASCII-Zeichen gespeicherte Datei ist eine Textdatei .

Alle Zeichen werden im ASCII-Format gespeichert und numerische Daten können entweder im ASCII- oder Binärformat gespeichert werden.

Es gibt eine Ganzzahl von 100. Wenn sie in Form eines ASCII-Codes auf der Festplatte ausgegeben wird, belegt sie 3 Bytes auf der Festplatte (ein Byte für jedes Zeichen), und wenn sie in Binärform ausgegeben wird, belegt sie nur 4 Bytes auf der Festplatte (Daten). im Speicher in binärer Form abgelegt).

Fügen Sie hier eine Bildbeschreibung ein

3. Dateipuffer

Der ANSIC-Standard verwendet das „Pufferdateisystem“ zur Verarbeitung von Datendateien. Das sogenannte Pufferdateisystem bedeutet, dass das System automatisch einen „Dateipuffer“ im Speicher für jede im Programm verwendete Datei erstellt. Die vom Speicher auf die Festplatte ausgegebenen Daten werden zuerst an den Ausgabepuffer 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 Eingabepuffer im Speicher eingegeben. Anschließend werden die Daten vom Puffer an den Programmdatenbereich (Programmvariablen usw.) gesendet. Einer nach dem anderen. Die Größe des Puffers wird durch das C-Kompilierungssystem bestimmt. Natürlich müssen solche Bedingungen nicht immer erfüllt sein, um Daten zu übertragen und zu übertragen. Wenn eine Notfallbedingung auftritt, können sie direkt übertragen werden, ohne darauf warten zu müssen, dass der Puffer voll ist.

Fügen Sie hier eine Bildbeschreibung ein

#include <stdio.h>
#include <windows.h>
int main()
{
    
    
	FILE* pf = fopen("test.txt", "w");
	fputs("abcdef", pf);//此时只是将数据放到了缓冲区当中
	printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");
	Sleep(10000);
	printf("刷新缓冲区\n");
	fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到了磁盘当中
	printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");
	Sleep(10000);
	//fclose在关闭文件的时候也会刷新缓冲区
	fclose(pf);
	pf = NULL;
	return 0;
}

Dieser Code kann selbst überprüft werden. Nachdem die fputs-Funktion ausgeführt wurde, öffnen Sie die Datei test.txt. Sie werden feststellen, dass keine Daten vorhanden sind. Nach dem Aktualisieren des Puffers werden die Daten in der Datei test.txt angezeigt. Die Spülfunktion kann als Notfall betrachtet werden.
Hinweis: Wegen der Existenz des Puffers. Beim Bearbeiten von Dateien in der Sprache C ist es am Ende des Dateivorgangs erforderlich, den Puffer zu aktualisieren oder die Datei zu schließen. Andernfalls kann es zu Problemen beim Lesen und Schreiben von Dateien kommen.

2. Dateioperation

1. Dateizeiger

Im Cache-Dateisystem ist das Schlüsselkonzept „ Dateitypzeiger “, der als „ Dateizeigerbezeichnet wird .
Jede verwendete Datei hat einen entsprechenden Dateiinformationsbereich im Speicher geöffnet, in dem die relevanten Informationen der Datei gespeichert werden (z. B. der Name der Datei, der Status der Datei und der aktuelle Speicherort der Datei usw.). ). Diese Informationen werden in einer Strukturvariablen gespeichert. Der Strukturtyp wird vom System mit dem Namen FILE deklariert .

Beispielsweise verfügt die von der VS2013-Kompilierungsumgebung bereitgestellte Headerdatei stdio.h über 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;

Immer wenn eine Datei geöffnet wird, erstellt das System automatisch eine Variable der FILE-Struktur entsprechend der Situation der Datei und füllt die Informationen aus. Im Allgemeinen wird die Variable der FILE-Struktur über einen FILE-Zeiger verwaltet. In dieser FILE-Struktur Die erste A-Variable ist der Dateiname, und die entsprechende Datei kann über den Dateinamen verwaltet werden.

Erstellen Sie eine FILE*-Zeigervariable:

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

pf ist eine Zeigervariable, die auf Daten vom Typ FILE zeigt. Der pf-Zeiger kann auf den Dateiinformationsbereich (FILE-Strukturvariable) einer Datei verweisen, und der Dateiinformationsbereich enthält die spezifischen Details der test.txt-Datei, was auch möglich ist soll eine Datei sein. Der Inhalt des Informationsbereichs beschreibt die Datei.
Fügen Sie hier eine Bildbeschreibung ein

2. Öffnen und Schließen der Datei

Es gibt entsprechende Funktionen zum Öffnen und Schließen von Dateien. fopen () und fclose () erscheinen paarweise. Wie oben erwähnt, führt das Aktualisieren des Puffers oder das Schließen der Datei am Ende des Dateivorgangs zum Lesen und Dateien schreiben. Das Problem. Beim Schreiben eines Programms wird beim Öffnen einer Datei eine Zeigervariable FILE* zurückgegeben, die auf die Datei zeigt, was dem Herstellen einer Beziehung zwischen dem Zeiger und der Datei entspricht.

FILE * fopen ( const char * filename, const char * mode );

int fclose ( FILE * stream );

So öffnen Sie die Datei:

Methode zum Öffnen von Dateien Bedeutung Wenn die angegebene Datei nicht existiert
„r“ (schreibgeschützt) Um Daten einzugeben, öffnen Sie eine vorhandene Textdatei schief gehen
„w“ (nur Schreiben) Um Daten auszugeben, öffnen Sie eine Textdatei eine neue Datei erstellen
„a“ (anhängen) Fügen Sie Daten am Ende der Textdatei hinzu schief gehen
„rb“ (schreibgeschützt) Um Daten einzugeben, öffnen Sie eine Binärdatei schief gehen
„wb“ (nur Schreiben) Um Daten auszugeben, öffnen Sie eine Binärdatei eine neue Datei erstellen
„ab“ (anhängen) Daten an das Ende einer Binärdatei anhängen schief gehen
„r+“ (lesen und schreiben) Öffnen Sie eine Textdatei zum Lesen und Schreiben schief gehen
„w+“ (lesen und schreiben) Schlagen Sie zum Lesen und Schreiben eine neue Datei vor eine neue Datei erstellen
„a+“ (lesen und schreiben) Öffnen Sie eine Datei zum Lesen und Schreiben am Ende der Datei eine neue Datei erstellen
„rb+“ (lesen und schreiben) Öffnen Sie eine Binärdatei zum Lesen und Schreiben schief gehen
„wb+“ (lesen und schreiben) Erstellen Sie eine neue Binärdatei zum Lesen und Schreiben eine neue Datei erstellen
„ab+“ (lesen und schreiben) Öffnen Sie eine Binärdatei zum Lesen und Schreiben am Ende der Datei eine neue Datei erstellen

Beispiele für das Öffnen und Schließen von Dateien:

#include <stdio.h>
int main ()
{
    
    
  FILE* pFile = fopen ("test.txt","w");
  if (pFile!=NULL)
 {
    
    
    fputs ("Hello,World!",pFile);
    fclose (pFile);
 }
  return 0;
}

3. Sequentielles Lesen und Schreiben von Dateien

Funktion Funktionsname gelten
Zeicheneingabefunktion fgetc alle Eingabeströme
Zeichenausgabefunktion fputc alle Ausgabeströme
Textzeilen-Eingabefunktion fgets alle Eingabeströme
Textzeilenausgabefunktion fputs alle Ausgabeströme
Formateingabefunktion fscanf alle Eingabeströme
Ausgabefunktion formatieren fprintf alle Ausgabeströme
Binäreingang Angst dokumentieren
binäre Ausgabe fwrite dokumentieren

Hinweis: Die folgenden Verfahren entsprechen paarweise

3.1 Zeichenausgabefunktion (fputc())

Fügen Sie hier eine Bildbeschreibung ein

//将26个英文字母输出到test.txt文件中
#include <stdio.h>
int main()
{
    
    
	FILE* pf = (FILE*)fopen("test.txt", "w");
	if (pf==NULL)
	{
    
    
		perror("fopen");
		return -1;
	}
	for (int i = 0; i < 26; i++)
	{
    
    
		fputc('a'+i, pf);
	}
    fclose(pf);
    pf=NULL;
	return 0;
}

3.2 Zeicheneingabefunktion (fgetc())

Fügen Sie hier eine Bildbeschreibung ein

//将26个英文字母输入到内存当中并将其打印在屏幕上
#include <stdio.h>
int main()
{
    
    
	FILE* pf = (FILE*)fopen("test.txt", "r");
	if (pf==NULL)
	{
    
    
		perror("fopen");
		return -1;
	}
	char c = 0;
	while ((c = fgetc(pf)) != EOF)
	{
    
    
		printf("%c", c);
	}
	fclose(pf);
    pf=NULL;
	return 0;
}

3.3 Textzeilenausgabefunktion (fputs())

Fügen Sie hier eine Bildbeschreibung ein

#include <stdio.h>
int main()
{
    
    
	FILE* pf = (FILE*)fopen("test.txt", "w");
	if (pf==NULL)
	{
    
    
		perror("fopen");
		return -1;
	}
	fputs("Hello,World! ", pf);
    fclose(pf);
    pf=NULL;
	return 0;
}

3.4 Textzeilen-Eingabefunktion (fgets())

Fügen Sie hier eine Bildbeschreibung ein

#include <stdio.h>
int main()
{
    
    
	FILE* pf = (FILE*)fopen("test.txt", "r");
	if (pf==NULL)
	{
    
    
		perror("fopen");
		return -1;
	}
	char arr[10] = {
    
     0 };
	fgets(arr, 7, pf);
	printf("%s", arr);
	fclose(pf);
	pf=NULL;
	return 0;
}

3.5 Formatierte Ausgabefunktion (fprintf())

Fügen Sie hier eine Bildbeschreibung ein

#include <stdio.h>
int main()
{
    
    
	FILE* pf = (FILE*)fopen("test.txt", "w");
	if (pf==NULL)
	{
    
    
		perror("fopen");
		return -1;
	}
	fprintf(pf, "%s %d", "zhuxu", 115);
	fclose(pf);
	pf = NULL;
	return 0;
}

3.6 Eingabefunktion formatieren (fscanf())

Fügen Sie hier eine Bildbeschreibung ein

#include <stdio.h>
int main()
{
    
    
	FILE* pf = (FILE*)fopen("test.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return -1;
	}
	char str[10] = {
    
     0 };
	int n = 0;
	fscanf(pf, "%s", str);
	fscanf(pf, "%d", &n);
	printf("%d\n", n);
	printf("%s\n",str);
	fclose(pf);
	pf = NULL;
	return 0;
}

3.7 Binärausgabe (fwrite())

Fügen Sie hier eine Bildbeschreibung ein
Funktionsparameter:

ptr Zeiger auf den Speicherblock, die minimale Speicherplatzgröße beträgt (Größe*Anzahl) Bytes.
Größe Die Größe in Bytes jedes zu lesenden Elements.
count Die Anzahl der Elemente, jedes Element hat die Größe Bytes.
stream Zeiger auf ein FILE-Objekt, das den Eingabestream angibt.

#include <stdio.h>
int main()
{
    
    
	char buffer[] = {
    
     'x', 'y', 'z' };
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return -1;
	}
	fwrite(buffer,1,3,pf);
	fclose(pf);
	return 0;
}

3.8 Binäreingang (fread())

Fügen Sie hier eine Bildbeschreibung ein

#include <stdio.h>
int main()
{
    
    
	char buffer[5] = {
    
     0 };
	FILE* pf = fopen("test.txt", "rb");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return -1;
	}
	fread(buffer, 1, 3, pf);
	printf("%c ", buffer[0]);
	printf("%c ", buffer[1]);
	printf("%c ", buffer[2]);
	return 0;
}

4. Zufälliges Lesen und Schreiben von Dateien

4.1 fseek-Funktion

Positioniert den Dateizeiger basierend auf der Position und dem Offset des Dateizeigers.

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

Fügen Sie hier eine Bildbeschreibung ein

#include <stdio.h>
int main ()
{
    
    
	FILE* pf = fopen ("test.txt","w");
  	fputs ( "This is an apple." , pf );
  	fseek ( pf , 9 , SEEK_SET );
  	fputs ( " sam" , pf );
 	fclose ( pf );
  	return 0;
}
// This is a sample.

int main()
{
    
    
	FILE* pf = fopen ("test.txt","w");
	fputs("This is an apple.", pf);
	fseek(pf, -8, SEEK_END);
	fputs(" sam", pf);
	fclose(pf);
	return 0;
}

4.2 ftell-Funktion

Gibt den Offset des Dateizeigers relativ zur Startposition zurück

long int ftell ( FILE * stream );
//计算test.txt文件里的数据长度
#include <stdio.h>

int main ()
{
    
    
  	long size;
    FILE *pf = fopen ("test.txt","r");
  	if (pf == NULL)
	{
    
    
		perror("fopen");
		return -1;
	}
    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.3 Rückspulfunktion

Gibt die Position des Dateizeigers an den Anfang der Datei zurück

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

4. Endurteil einreichen

  1. Ob das Lesen der Textdatei abgeschlossen ist, beurteilen Sie, ob der Rückgabewert EOF (fgetc) oder NULL (fgets) ist.

fgetc beurteilt, ob es EOF ist.
fgets beurteilt, ob der Rückgabewert NULL ist.

Hinweis: Während des Dateilesevorgangs kann der Rückgabewert der feof-Funktion nicht verwendet werden, um direkt zu beurteilen, ob die Datei beendet ist. Stattdessen wird es angewendet, wenn das Lesen der Datei endet, und beurteilt, ob das Lesen fehlschlägt oder das Ende der Datei erreicht ist.

  1. 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.

fread beurteilt, ob der Rückgabewert kleiner als die tatsächlich zu lesende Zahl ist.

Die Textdatei wird korrekt beurteilt

#include <stdio.h>
#include <stdlib.h>
int main()
{
    
    
    int c; // 注意:int,非char,要求处理EOF
    FILE* fp = fopen("test.txt", "r");
  	if (pf == NULL)
	{
    
    
		perror("fopen");
		return -1;
	}
 //fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
    while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环
   	{
    
     
       	putchar(c);
   	}
 //判断是什么原因结束的
    if (ferror(fp))
        puts("I/O error when reading");
    else if (feof(fp))
        puts("End of file reached successfully");
    fclose(fp);
    fp = NULL;
    return 0;
}

Die Binärdatei wird korrekt beurteilt

#inlcude <stdio.h>
int main(void)
{
    
    
    double a[5] = {
    
    1.0,2.0,3.0,4.0,5.0};
    double b = 0.0;
    size_t ret_code = 0;
    FILE *fp = fopen("test.txt", "wb"); // 必须用二进制模式
    fwrite(a, sizeof(*a), 5, fp); // 将 a 数的元素写到test.txt文件中
    fclose(fp); 
    fp = fopen("test.txt","rb");
    // 将 a 数组的元素读到变量 b 中,返回值为读取数据的个数
    while((ret_code = fread(&b, sizeof(double), 1, fp))>=1)
   	{
    
    
        printf("%lf\n",b);
   	}
    if (feof(fp))
        printf("Error reading test.bin: unexpected end of file\n");
    else if (ferror(fp)) {
    
    
        perror("Error reading test.bin");
   	}
    fclose(fp);
    fp = NULL;
    return 0;
}

Ich denke du magst

Origin blog.csdn.net/weixin_47648037/article/details/127259629
Empfohlen
Rangfolge