6. File operation

FILE pointer

In C language, each used file opens up a corresponding file information area in the memory, which is used to store the related information of the file (such as the name of the file, the file status and the current location of the file, etc.). This information is stored in a structure variable. The structure type is declared by the system and named FILE. For example, the stdio.h header file provided by the VS2008 compilation environment has the following file type declaration:

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

The contents of the FILE type of different C compilers are not exactly the same, but they are similar. Whenever a file is opened, the system will automatically create a variable of the FILE structure according to the situation of the file, and fill in the information, so the user does not need to care about the details. Generally, a FILE pointer is used to maintain the variable of the FILE structure, which is more convenient to use.


Open and close files

open a file

The fopen function prototype:
FILE *fopen(const char *path, const char *mode);

Parameters: the first parameter is the file path, the second parameter is the way to open the file, the type is all string

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

If there is no such file, a file will be created

The second parameter selection
File usage meaning If the specified file does not exist
"R" (read) Open file for reading Error
"W" (write) Truncate the file to zero length or create a text file for writing Create a new file
"Rt" (read only) 1 Open a text file, only allow to read data Error
"Wt" (write only) Write only to open or create a text file, only allow to write data Create a new document
"A" (addition) Append data to the end of the text file Error
"Rb" (append) Open a binary file for reading Error
"Wb" (write only) Open a binary file for writing Create a new file
“Ab” (additional) Add data to the end of a binary file Error
"R+" (read and write) In order to read and write, open a text file Error
"W+" (read and write) In order to read and write, create a new file Create a new document
"A+" (read and write) Open a file, read and write at the end of the file Create a new file
"Rb+" (read and write) 2 Open a binary file for reading and writing Error
"Wb+" (read and write) In order to read and write, create a new binary file Create a new file
"Ab+" (read and write) Open a binary file, read and write at the end of the file Create a new file

Close file

The fclose function prototype:
int fclose(FILE *stream);

Parameters: The only parameter is the file pointer that needs to be closed


File read and write

Sequential read and write

Features Function name Apply to
Character output function fputc All output streams
Character input function fgetc All input streams
Text line output function fputs All output streams
Text line input function fgets All input streams
Formatted output function fprintf All output streams
Format input function fscanf All input streams
Binary output fwrite file
Binary input fread file
The fputc function prototype:
int fputc( int c, FILE *stream );

Parameters: The first parameter is the character to be written, and the second parameter is the file stream to be written

Usage example
    FILE* pFile = fopen("fputc.txt", "w");
	char* str = "This is a test of fputc!!\n";
	char* p_str = str;
	while ((*p_str != '\0') && fputc(*(p_str++), stdout) != EOF);
	p_str = str;
	while ((*p_str != '\0') && fputc(*(p_str++), pFile) != EOF);

The FILE pointer is actually a file stream, which is also a kind of stream, which is almost the same as the standard input and output stream.

The fgetc function prototype:
int fgetc( FILE *stream );

Parameters: stream is the destination stream to be read

Usage example
    //先使用fputs写一个文本文件
	FILE* pFile = fopen("fgetc.txt", "w");
	char* str = "This is a test of fgetc!!\n";
	fputs("Hello world from fgetc.\n", pFile);
	fclose(pFile);
	//使用fgetc读取这个文本文件的内容
	pFile = fopen("fgetc.txt", "r");
	while(feof(pFile) == 0){
		char ch = fgetc(pFile);
		fputc((char)ch, stdout);
	}
	fclose(pFile);
    

The fputs function prototype:
int fputs( const char *string, FILE *stream );

Parameters: the first is the string to be written to the file, the second parameter is the output stream

Usage example
    FILE* pFile = fopen("fputs.txt", "w");
	char* str = "This is a test of fputs!!\n";
    fputs(str, pFile);

The fgets function prototype:
char *fgets(char *restrict s, int n, FILE *restrict stream);

Parameters: read a string of up to n characters from the stream and save it to the s character

Usage example
//先使用fputs写入一个文本文件
	FILE* pFile = fopen("fgets.txt", "w");
	char* str = "This is a test of fgets!!\n";
	fputs(str, pFile);
	fclose(pFile);
	//再使用fgets读
	char line[1000];
	if ((pFile = fopen("fgets.txt", "r")) != NULL)
	{
		if (fgets(line, 1000, pFile) == NULL)
			printf("fgets error\n");
		else
			printf("%s", line);
		fclose(pFile);
	}

The fprintf function prototype:
int fprintf( FILE *stream, const char *format [, argument ]...);

Parameters: stream the stream to be output, format is the format control string, argument is multiple variables

Usage example
    int    i = 10;
	double fp = 1.5;
	char   s[] = "this is a string";
	char   c = '\n';

	FILE* stream = fopen("fprintf.out", "w");
	fprintf(stream, "%s%c", s, c);
	fprintf(stream, "%d\n", i);
	fprintf(stream, "%f\n", fp);
	fclose(stream);
	system("type fprintf.out");

The difference between printf and standard output is that the first specified output stream parameter is added. The content of the out suffix file can be directly printed to the standard output stream using system.


The fscanf function prototype:
int fscanf( FILE *stream, const char *format [, argument ]... );

Parameters: parse the data from the stream according to format and store them in arguments in turn

Usage example
    //先使用fprintf向文件输入
    int    i = 10;
	double fp = 1.5;
	char   s[] = "string";
	char   c = 'U';

	FILE* stream = fopen("fscanf.out", "w");
	fprintf(stream, "%s %c", s, c);
	//s字符串需要scanf读取的话,没有空格和换行的字符串请用空格与后面的变量隔开,如果字符串含空格,建议将字符串作为一整行用fgets读取
	fprintf(stream, "%d\n", i);
	fprintf(stream, "%f\n", fp);
	fclose(stream);
	
	//使用fscanf读取文件数据
	stream = fopen("fscanf.out", "r");
	fscanf(stream, "%s", &s);
	fscanf(stream, "%c", &c); //捕捉空格
	fscanf(stream, "%c", &c);
	printf("%s %c\n", s, c);
	fscanf(stream, "%d", &i);
	fscanf(stream, "%f", &fp);
	printf("%d\n%f\n", i, fp);
	fclose(stream);

The fwrite function prototype:
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );

Parameters: buffer is the data to be written, size is the byte size of the element, count is the number of elements, stream is the destination stream to be written

Usage example
    FILE* stream = fopen("fwrite.out", "w+t");
	char list[] = "abcdefghijklmnopqrstuvwxyz";
	if (stream  != NULL)	{
		char numwritten = fwrite(list, sizeof(char), strlen(list), stream);
		printf("Wrote %d items\n", numwritten);
		fclose(stream);
	}
	system("type fread.out");

fwrite can write count characters, integer or size strings


The fread function prototype:
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );

Parameters: buffer is the data storage area to be read, size is the size of a single element, count is

Usage example
    //读取上面fwrite保存的fwrite.out文件
    if ((stream = fopen("fwrite.out", "r+t")) != NULL)
	{
		char numread = fread(list, sizeof(char), 26, stream);
		printf("Number of items read = %d\n", numread);
		printf("Contents of buffer = %.26s\n", list);
		fclose(stream);
	}
	else
		printf("File could not be opened\n");

Random read and write

Jump to any position of the file pointer

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

Parameters: stream is the stream being operated on, offset is the offset, origin is the starting position of the reference offset

Benchmark Offset reference position
SEEK_SET Start of file
SEEK_CUR The current position pointed to by the file pointer
SEEK_END End of file
Usage example
    FILE* pFile = fopen("example.txt", "wb");
	fputs("This is an apple.", pFile);
	fseek(pFile, 9, SEEK_SET);
	fputs(" sam", pFile);
	fclose(pFile);
	system("type example.txt");

Returns the offset of the file pointer relative to the starting position

ftell function prototype
long ftell( FILE *stream );

Parameters: stream is the target stream to get the offset

Usage example
    FILE* stream = fopen("ftell.c", "w+");
	srand(time(NULL));
	int charNumber = 150;
	while (charNumber--)
		fputc(rand() % 57 + 65, stream);

	//得到当前的偏移量
	long position;
	position = ftell(stream);
	printf("Position after trying to read 100 bytes: %ld\n",
		position);
	fclose(stream);


The position of the file pointer returns to the beginning of the file

rewind function prototype
void rewind ( FILE * stream );

Parameters: stream is the target stream that points the file pointer to the beginning of the file

Usage example
    //写一个文件用于测试
    char list[100];
	FILE* stream = fopen("rewind.c", "w");
	srand(time(NULL));
	int charNumber = 150;
	while (charNumber--)
		fputc(rand() % 57 + 65, stream);
	fclose(stream);
	stream = fopen("rewind.c", "r");
	
	//读
	fread(list, sizeof(char), 100, stream);
	char position = ftell(stream);
	printf("Position after read: %ld\n",
		position);
		
	//文件指针回到文件首
	rewind(stream);
	position = ftell(stream);
	printf("Position after back to start: %ld\n",
		position);
	fclose(stream);

Just finish writing and do not close the file stream to read the file fingerprint offset is a negative number

FILE* stream = fopen("rewind.c", "w");
	srand(time(NULL));
	int charNumber = 150;
	while (charNumber--)
		fputc(rand() % 57 + 65, stream);
	char position = ftell(stream);
	printf("Position after write: %ld\n", position);

File end judgment

feof function prototype
int feof( FILE *stream );

Parameters: Determine whether the file pointer reaches the target stream at the end of the file

fgetc, fgetc, fread, fprintf will return EOF when the end of the file is read

Usage example
    //创建feof.c
	FILE* stream = fopen("feof.c", "w");
	srand(time(NULL));
	int charNumber = 80;
	while (charNumber--)
		fputc(rand() % 57 + 65, stream);
	fclose(stream);

	//读feof.c
	int  count, total = 0;
	char buffer[100];
	if ((stream = fopen("feof.c", "r")) == NULL)
		exit(1);


	//结合feof就可以循环读到文件结尾
	/* Cycle until end of file reached: */
	while (!feof(stream))
	{
		/* Attempt to read in 10 bytes: */
		count = fread(buffer, sizeof(char), 100, stream);
		if (ferror(stream)) {
			perror("Read error");
			break;
		}

		/* Total up actual bytes read */
		total += count;
	}
	printf("Number of bytes read = %d\n", total);
	fclose(stream);

Example of reading a binary file

#include <stdio.h>
enum { SIZE = 5 };
int main(void)
{
	double a[SIZE] = { 1.0,2.0,3.0,4.0,5.0 };
	double b = 0.0;
	size_t ret_code = 0;
	FILE* fp = fopen("test.bin", "wb"); // 必须用二进制模式
	fwrite(a, sizeof(*a), SIZE, fp); // 写 double 的数组
	fclose(fp);
	fp = fopen("test.bin", "rb");
	// 读 double 的数组
	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;
}


  1. Equivalent to r+t ↩︎

  2. Equivalent to r+b ↩︎

Guess you like

Origin blog.csdn.net/qq_43808700/article/details/114106618