Operación de archivo [lenguaje C] (explicación súper detallada)

1. ¿Qué es un documento?

Los archivos informáticos son un tipo de archivos. A diferencia de los soportes de archivos ordinarios, este tipo de archivos es una colección de información almacenada en una computadora con un disco duro como soporte.
En programación, generalmente hablamos de dos tipos de archivos: archivos de programa y archivos de datos.

Archivos de programa: incluidos los archivos de programa de origen (sufijo .c), archivos de destino (sufijo de entorno de Windows .obj), programas ejecutables (sufijo de entorno de Windows .exe).
Archivo de datos: el contenido del archivo no es necesariamente el programa, sino los datos leídos y escritos cuando el programa se está ejecutando, como el archivo del que el programa necesita leer datos o el archivo que genera el contenido.

El contenido de este artículo está dirigido a archivos de datos . La entrada y salida de datos aprendidos antes se basa en el terminal, es decir, los datos se ingresan desde el teclado del terminal y los resultados de la ejecución se muestran en el monitor. Sin embargo, la salida y la entrada de datos también se pueden transferir entre la memoria y el archivo, que también es el objeto discutido en este artículo.La salida de los datos se escribe desde la memoria al archivo, y la entrada de los datos se leer desde el archivo a la memoria ir .

1. Nombre del archivo

Un archivo debe tener un identificador de archivo único, y el nombre del archivo también es el identificador de la existencia del archivo.El sistema operativo lo controla y administra de acuerdo con el nombre del archivo. El nombre de archivo existe para la identificación y referencia del usuario.
El nombre del archivo consta de 3 partes: ruta del archivo + tronco del nombre del archivo + sufijo del archivo
Por ejemplo:c:\code\test\test.txt

Ruta del archivo: c:\code\test\
nombre del archivo troncal: test
sufijo del archivo:.txt

2. Tipo de archivo

Dependiendo de cómo se organicen los datos, los archivos de datos se pueden clasificar como archivos de texto o archivos binarios.
Los datos se almacenan en forma de binario en la memoria interna. Si se envían al almacenamiento externo sin conversión, es un archivo binario . Si es necesario almacenarlos en forma de código ASCII en el almacenamiento externo, debe convertirse antes del almacenamiento. Un archivo almacenado en forma de caracteres ASCII es un archivo de texto .

Todos los caracteres se almacenan en formato ASCII y los datos numéricos se pueden almacenar en formato ASCII o binario.

Hay un número entero 100, si se envía al disco en forma de código ASCII, ocupará 3 bytes en el disco (un byte para cada carácter), y si se envía en forma binaria, solo ocupará 4 bytes en el disco (datos en la memoria almacenada en forma binaria).

inserte la descripción de la imagen aquí

3. Búfer de archivos

El estándar ANSIC utiliza el "sistema de archivos de búfer" para procesar archivos de datos. El llamado sistema de archivos de búfer significa que el sistema crea automáticamente un "búfer de archivos" en la memoria para cada archivo que se utiliza en el programa. La salida de datos de la memoria al disco se enviará primero al búfer de salida en la memoria y luego se enviará al disco juntos después de que se llene el búfer. Si los datos se leen del disco a la computadora, los datos se leen del archivo del disco y se ingresan al búfer de entrada en la memoria, y luego los datos se envían desde el búfer al área de datos del programa (variables de programa, etc.) uno a uno. El tamaño del búfer está determinado por el sistema de compilación C. Por supuesto, no es necesario cumplir con tales condiciones todo el tiempo para transmitir y transmitir datos.Si se encuentra una condición de emergencia, se puede transmitir directamente sin esperar a que el búfer esté lleno.

inserte la descripción de la imagen aquí

#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;
}

Este código se puede verificar por sí mismo. Después de ejecutar la función fputs, abra el archivo test.txt y encontrará que no hay datos. Después de actualizar el búfer, los datos aparecerán en el archivo test.txt. La función fflush puede considerarse una emergencia.
Nota: Debido a la existencia del búfer. Al operar archivos en lenguaje C, es necesario actualizar el búfer o cerrar el archivo al final de la operación del archivo. Si no lo hace, puede causar problemas para leer y escribir archivos.

2. Operación de archivo

1. Puntero de archivo

En el sistema de archivos de caché, el concepto clave es " puntero de tipo de archivo ", denominado " puntero de archivo ".
Cada archivo utilizado ha abierto un área de información de archivo correspondiente en la memoria, que se utiliza para almacenar la información relevante del archivo (como el nombre del archivo, el estado del archivo y la ubicación actual del archivo, etc.) ). Esta información se almacena en una variable de estructura. El tipo de estructura es declarado por el sistema, llamado ARCHIVO .

Por ejemplo, el archivo de encabezado stdio.h proporcionado por el entorno de compilación VS2013 tiene la siguiente declaración de tipo de archivo:

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

typedef struct _iobuf FILE;

Cada vez que se abre un archivo, el sistema creará automáticamente una variable de la estructura FILE de acuerdo con la situación del archivo y completará la información. Generalmente, la variable de la estructura FILE se mantiene a través de un puntero FILE. En esta estructura FILE , la primera variable A es el nombre del archivo, y el archivo correspondiente se puede mantener a través del nombre del archivo.

Cree una variable de puntero FILE*:

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

pf es una variable de puntero que apunta a datos de tipo ARCHIVO. El puntero pf puede apuntar al área de información de archivo (variable de estructura de ARCHIVO) de un archivo, y el área de información de archivo contiene los detalles específicos del archivo test.txt, que también puede ser se dice que es un archivo El contenido del área de información describe el archivo.
inserte la descripción de la imagen aquí

2. Apertura y cierre de expedientes

Hay funciones correspondientes para abrir y cerrar archivos. fopen () y fclose () aparecen en pares. Como se mencionó anteriormente, si el búfer se actualiza o el archivo no se cierra al final de la operación del archivo, conducirá a la lectura y escribir archivos El problema. Al escribir un programa, al abrir un archivo, se devolverá una variable puntero FILE* para apuntar al archivo, lo que equivale a establecer la relación entre el puntero y el archivo.

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

int fclose ( FILE * stream );

Cómo abrir el archivo:

método de apertura de archivos significado Si el archivo especificado no existe
"r" (solo lectura) Para ingresar datos, abra un archivo de texto existente ir mal
"w" (solo escritura) Para generar datos, abra un archivo de texto crear un nuevo archivo
"a" (añadir) Agregar datos al final del archivo de texto ir mal
"rb" (solo lectura) Para ingresar datos, abra un archivo binario ir mal
"wb" (solo escritura) Para generar datos, abra un archivo binario crear un nuevo archivo
"ab" (añadir) añadir datos al final de un archivo binario ir mal
"r+" (leer y escribir) Abrir un archivo de texto para leer y escribir ir mal
"w+" (leer y escribir) Para leer y escribir, sugiera un nuevo archivo crear un nuevo archivo
"a+" (leer y escribir) Abra un archivo para leer y escribir al final del archivo crear un nuevo archivo
"rb+" (leer y escribir) Abrir un archivo binario para leer y escribir ir mal
"wb+" (leer y escribir) Crear un nuevo archivo binario para leer y escribir crear un nuevo archivo
"ab+" (leer y escribir) Abra un archivo binario para leer y escribir al final del archivo crear un nuevo archivo

Ejemplos de apertura y cierre de archivos:

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

3. Lectura y escritura secuencial de archivos

Función Nombre de la función aplicar para
función de entrada de caracteres fgetc todos los flujos de entrada
función de salida de caracteres fputc todos los flujos de salida
función de entrada de línea de texto fgets todos los flujos de entrada
función de salida de línea de texto entradas todos los flujos de salida
función de entrada de formato fscanf todos los flujos de entrada
función de formato de salida fprintf todos los flujos de salida
entrada binaria miedo documento
salida binaria escribir documento

Nota: Los siguientes procedimientos se corresponden por pares

3.1 Función de salida de caracteres (fputc())

inserte la descripción de la imagen aquí

//将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 Función de entrada de caracteres (fgetc())

inserte la descripción de la imagen aquí

//将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 Función de salida de línea de texto (fputs())

inserte la descripción de la imagen aquí

#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 Función de entrada de línea de texto (fgets())

inserte la descripción de la imagen aquí

#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 Función de salida formateada (fprintf())

inserte la descripción de la imagen aquí

#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 Función de formato de entrada (fscanf())

inserte la descripción de la imagen aquí

#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 Salida binaria (fwrite())

inserte la descripción de la imagen aquí
Parámetros de la función:

ptr Puntero al bloque de memoria, el tamaño de espacio mínimo es (tamaño*recuento) bytes.
tamaño El tamaño en bytes de cada elemento a leer.
count El número de elementos, cada elemento tiene un tamaño de bytes.
stream Puntero a un objeto FILE que especifica el flujo de entrada.

#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 Entrada binaria (fread())

inserte la descripción de la imagen aquí

#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. Lectura y escritura aleatoria de archivos.

4.1 función de búsqueda

Posiciona el puntero de archivo en función de la posición y el desplazamiento del puntero de archivo.

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

inserte la descripción de la imagen aquí

#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;
}

Función 4.2 ftell

Devuelve el desplazamiento del puntero del archivo en relación con la posición inicial

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 función de rebobinado

Devuelve la posición del puntero del archivo al principio del archivo.

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. Expediente fin sentencia

  1. Si la lectura del archivo de texto ha terminado, juzgue si el valor de retorno es EOF (fgetc) o NULL (fgets)

fgetc juzga si es EOF
fgets juzga si el valor de retorno es NULL.

Nota: Durante el proceso de lectura del archivo, el valor de retorno de la función feof no se puede usar para juzgar directamente si el archivo ha terminado. En su lugar, se aplica cuando finaliza la lectura del archivo, juzgando si la lectura no finaliza o si se encuentra el final del archivo.

  1. Juzgar el final de la lectura del archivo binario y juzgar si el valor de retorno es menor que el número real que se va a leer.

fread juzga si el valor devuelto es menor que el número real que se va a leer.

El archivo de texto se juzga correctamente.

#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;
}

El archivo binario se juzga correctamente.

#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;
}

Supongo que te gusta

Origin blog.csdn.net/weixin_47648037/article/details/127259629
Recomendado
Clasificación