目录

1. 什么是文件

2. 为什么要有文件

3. 文件名

4. 文件类型

5. 文件指针

6. 文件的打开和关闭

7. 文件的顺序读写

7.1. fgetc 

7.2. fputc

7.3. fgets

7.4. fputs

7.5. fscanf

7.6. fprintf

7.8. sscanf

7.9. sprintf

7.9. fread

7.10. fwrite

8. 文件的随机读写

8.1. fseek

8.2. ftell

8.3. rewind

9. 文件结束的判定


1. 什么是文件

2. 为什么要有文件

3. 文件名

4. 文件类型

C文件操作-LMLPHP

C文件操作-LMLPHP

5. 文件指针

6. 文件的打开和关闭

// 函数原型
// filename: 文件名
// mode: 打开文件的方式
// return val: 返回一个文件指针,这个指针指向这个被打开的文件
FILE *fopen( const char *filename, const char *mode );

// 函数原型
// 关闭一个被打开的文件
// stream: 对应的文件指针
// return val: 如果成功关闭,返回0;失败返回EOF
int fclose( FILE *stream );
void Test1(void)
{
	// 以文本写的方式打开文件
	FILE* fp = fopen("log.txt", "w");
	// 打开失败返回NULL
	if (fp == NULL)
	{
		perror("open failed");
		exit(-1);
	}
	else
	{
		// 关闭文件
		fclose(fp);
	}
}

7. 文件的顺序读写

7.1. fgetc 

// Read a character from a stream or stdin;
// 读取失败会返回EOF(end of file)
// success: 返回读取的字符
int fgetc( FILE *stream );
void Test2(void)
{
    // 以文本读打开一个文件
	FILE* fp = fopen("Test.c", "r");
	assert(fp);
    // 如果没有遇到EOF,就继续读
	while (!feof(fp))
	{
        //每次读取一个字符,并向标准输出写入
		printf("%c", fgetc(fp));
	}
    // 关闭一个文件
	fclose(fp);
}

7.2. fputc

Writes a character to a stream or to stdout.
// ch: 你要写入的字符
// stream: 你要向哪个流写入
// success: return ch
// failed: return EOF
int fputc( int c, FILE *stream );
void Test3(void)
{
	char ch = 'a';
	while (ch <= 'z')
	{
        // 向标准输出(stdout)写入ch
		fputc(ch, stdout);
		++ch;
	}
}

7.3. fgets

//Get a string from a stream.

// string: 数据的存储位置
// n: 每次最大读取字符的个数
// stream: 从那个流中读?
// success: 返回读取字符串的起始位置
// failed: 返回NULL
char *fgets( char *string, int n, FILE *stream );

#define BUFFER_MAX 64
void Test4(void)
{
	char str[BUFFER_MAX] = { 0 };
	FILE* fp = fopen("Test.c", "r");
	assert(fp);
	while (fgets(str, BUFFER_MAX, fp) != NULL)
	{
		printf("%s", str);
	}
	fclose(fp);
}

7.4. fputs

// Write a string to a stream.
// string 你要写入的字符串的起始地址
// stream 你要想哪个流写入
// success: 返回一个!负值
// failed: 返回EOF
int fputs( const char *string, FILE *stream );
void Test5(void)
{
	const char* str = "hehe\n";
	for (size_t i = 0; i < 5; ++i)
	{
        // 向标准输出写入特定字符串
		fputs(str, stdout);
	}
}

7.5. fscanf

//Read formatted data from a stream.
// 从特定流(所有输入流)读取格式化数据,与scanf十分类似
// 只不过scanf是固定的从标准输入流读取数据
int fscanf( FILE *stream, const char *format [, argument ]... );
#define BUFFER_MAX 64
void Test6(void)
{
	FILE* fp = fopen("log.txt1", "r");
	assert(fp);
	char str[BUFFER_MAX] = { 0 };
	while (!feof(fp))
	{
		fscanf(fp, "%s", str);
		printf("%s\n", str);
	}
	fclose(fp);
}

7.6. fprintf

// Print formatted data to a stream.
// 向特定流(所有输出流)写入格式化数据
// 与printf十分类似,不过printf是默认向标准输出流写入格式化数据
// success: 返回已写入的字节数
// failed: 返回一个负值
int fprintf( FILE *stream, const char *format [, argument ]...);
void Test7(void)
{
	const char* str = "haha\n";
	int* ptr = (int*)malloc(sizeof(int)* 5);
	for (size_t i = 0; i < 5; ++i)
	{
		// 其返回值代表每次写入的字节数
		// 向标准输出流写入特定字符串
		ptr[i] = fprintf(stdout, "%s", str);
	}
	for (int i = 0; i < 5; ++i)
	{
		printf("%d ", *(ptr + i));
	}
    free(ptr);
    ptr = NULL;
}

7.8. sscanf

// Read formatted data from a string

// buffer: 存储数据的起始地址
// sscanf  从一个字符串提取出格式化的数据
// failed: return EOF
int sscanf( const char *buffer, const char *format [, argument ] ... );
typedef struct PeoInfo
{
	char name[15];
	int age;
}Info;

void Test8(void)
{
	const char* buffer = "cuihua 18";
	Info tmp = { 0 };
    // 从buffer这个字符串提取成格式化的数据
	sscanf(buffer, "%s%d", tmp.name, &tmp.age);
	printf("%s %d\n", tmp.name,tmp.age);
}

7.9. sprintf

// Write formatted data to a string.

// buffer: 存储将格式化的数据转为stirng的结果
// sprintf 就是将格式化的数据转化为一个字符串

int sprintf( char *buffer, const char *format [, argument] ... );
void Test9(void)
{
	char buffer[BUFFER_MAX] = { 0 };
	Info tmp = { "cuihua", 18 };
    // 将格式化数据转化为一个字符串
	sprintf(buffer, "%s %d\n", tmp.name, tmp.age);
	printf("%s", buffer);
}

7.9. fread

// Reads data from a stream.
// buffer: 缓冲区
// size: 每次读取的字节数
// count: 要读取多少次
// stream: 从特定流读取

size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
void Test10(void)
{
	char str[BUFFER_MAX] = { 0 };
	FILE* fp = fopen("Test.c", "r"); 
	assert(fp);
	// 从fp这个流中读取BUFFER_MAX-1个有效字符
	fread(str, BUFFER_MAX - 1, 1, fp);
	printf("%s", str);
	fclose(fp);
}

7.10. fwrite

//Writes data to a stream.

// buffer: 指向被写入的数据
// size: 每次写多少个字节
// count: 写多少次
// stream: 向哪个流写入
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
void Test11(void)
{
	const char* str = "hehe\n";
	for (size_t i = 0; i < 5; ++i)
	{
		// 向标准输出流写入str这个指针指向的内容,每次写size个字节
		fwrite(str, strlen(str), 1, stdout);
	}
}

8. 文件的随机读写

8.1. fseek

//Moves the file pointer to a specified location.

// fseek 可以根据指针的位置 和 偏移量(offset) 来定位文件指针
// origin 初始位置
// SEEK_CUR 文件指针当前的位置
// SEEK_END 文件末尾的位置
// SEEK_SET 文件开始的位置
int fseek( FILE *stream, long offset, int origin );
void Test12(void)
{
	const char* str = "abcdefg";
	FILE* fp = fopen("data.txt", "w");
	assert(fp);
	fwrite(str, strlen(str), 1, fp); 
	// 此时data.txt的内容就是 abcdef
	fclose(fp);

	FILE* fp1 = fopen("data.txt", "r"); 
	char ch = 0;
	// 如果我按照顺序读取,那么第一次读必然是a
	ch = fgetc(fp1);
	printf("%c\n", ch);  // 必定是a

	// 那如果我此时像读取d呢
	// 由于此时的文件指针fp指向了b,那么 + 2就到了d
	// 故 offset = 2
	fseek(fp1, 2, SEEK_CUR);
	ch = fgetc(fp1);
	printf("%c\n", ch);  // d

	// 那如果我此时像读取最后一个字符呢,也就是g,如何读取呢?
    // SEEK_END 文件的末尾
	fseek(fp1, -1, SEEK_END);
	ch = fgetc(fp1);
	printf("%c\n", ch); // g
	fclose(fp1);
}

8.2. ftell

// Gets the current position of a file pointer.
// ftell函数可以返回当前文件指针相对于起始位置的偏移量
long ftell( FILE *stream );
void Test13(void)
{
	FILE* fp = fopen("data.txt", "r");
	// 这个文件的数据: abcdefg
	assert(fp);
	fseek(fp, -1, SEEK_END); // 此时这个文件指针指向g
	printf("%d\n", ftell(fp)); // 此时就是6
	fclose(fp);
}

8.3. rewind

//Repositions the file pointer to the beginning of a file.
// 让当前文件指针回到文件的起始位置
void rewind( FILE *stream );
void Test14(void)
{
	FILE* fp = fopen("data.txt", "r");
	// 这个文件的数据: abcdefg
	assert(fp);
	fseek(fp, -1, SEEK_END); // 此时这个文件指针指向g
	printf("%d\n", ftell(fp)); // 此时就是6

	rewind(fp); // 让这个文件指针回到文件的起始位置
	printf("%d\n", ftell(fp)); // 此时就是0
	fclose(fp);
}

9. 文件结束的判定

// Tests for end-of-file on a stream.
// 测试文件是如何结束的
// 如果遇到了EOF(即文件指针到了文件末尾),return !0
// otherwise, return 0

int feof( FILE *stream );
10-31 01:27