C语言-标准文件

概述

磁盘文件和设备文件

  • 磁盘文件:存储在磁盘介质上的文件
  • 设备文件:操作系统把链接主机的设备看成文件

磁盘文件分类

  • 文本文件:以编码存储在磁盘中
  • 二进制文件:以值存储在磁盘中
    图片解析
    在这里插入图片描述

文件打开和关闭

文件指针

在C语言中用一个指针变量指向一个文件,这个指针称为文件指针。

typedef struct
{
	short           level;	//缓冲区"满"或者"空"的程度 
	unsigned        flags;	//文件状态标志 
	char            fd;		//文件描述符
	unsigned char   hold;	//如无缓冲区不读取字符
	short           bsize;	//缓冲区的大小
	unsigned char   *buffer;//数据缓冲区的位置 
	unsigned        ar;	 //指针,当前的指向 
	unsigned        istemp;	//临时文件,指示器
	short           token;	//用于有效性的检查 
}FILE;
  • FILE是系统使用typedef定义出来的有关文件信息的一种结构体类型,结构中含有文件名、文件状态和文件当前位置等信息。

  • 声明FILE结构体类型的信息包含在头文件“stdio.h”中,一般设置一个指向FILE类型变量的指针变量,然后通过它来引用这些FILE类型变量。通过文件指针就可对它所指的文件进行各种操作。
    C语言中有三个特殊的文件指针由系统默认打开,用户无需定义即可直接使用:

  • stdin: 标准输入,默认为当前终端(键盘),我们使用的scanf、getchar函数默认从此终端获得数据。

  • stdout:标准输出,默认为当前终端(屏幕),我们使用的printf、puts函数默认输出信息到此终端。

  • stderr:标准出错,默认为当前终端(屏幕),我们使用的perror函数默认输出信息到此终端。

  • FILE* p

  • 当我们使用C库函数fopen打开一个文件,它会返回一个指向该文件所有信息的指针。我们对文件进行读写都需要依赖这个指针

文件的打开

fopen()
每个文件在使用之前必须打开

#include <stdio.h>
FILE * fopen(const char * filename, const char * mode);
  • 功能:打开文件
  • 参数:
    • filename:需要打开的文件名,根据需要加上路径
    • mode:打开文件的模式设置
  • 返回值:
    • 成功:文件指针
    • 失败:NULL
  • mode:文件打开的方式(r,w,a,rb,wb,ab,ab,r+,w+,a+)
    示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int myFopen()
{
	// 打开文件
	FILE* fp = NULL;
	// 打开当前目录下的test.txt
	// 以只读的方式打开文件,文件不存在会报错
	 // fp = fopen("test.txt", "r");
	// 以只写的方式打开文件,文件不存在会新建,文件存在会清空
	fp = fopen("test.txt", "w");
	if (fp == NULL)
	{
		perror("fopen"); // fopen: No such file or directory
		return -1;
	}
	//  关闭文件
	fclose(fp);
}

int main()
{
	myFopen();
	return 0;
}

文件的关闭

#include <stdio.h>
int fclose(FILE * stream);
  • 功能:
    • 关闭先前fopen()打开的文件。此动作让缓冲区的数据写入文件中,并释放系统所提供的文件资源。
  • 参数:
    • stream:文件指针
  • 返回值:
    • 成功:0
    • 失败:-1

文件的顺序读写

按照字符读写文件fgetc和fputc

写文件

#include <stdio.h>
int fputc(int ch, FILE * stream);
  • 功能:
    • 将ch转换为unsigned char后写入stream指定的文件中
  • 参数:
    • ch:需要写入文件的字符
    • stream:文件指针
  • 返回值:
    • 成功:成功写入文件的字符
    • 失败:返回-1

示例代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int myFputc() 
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "w");
	// 字符方式写文件
	char buf[] = "hello directory";
	int n = sizeof(buf) / sizeof(buf[0]);
	int ch;
	for (int i = 0;i < n;i++)
	{
		ch = fputc(buf[i], fp);
		printf("%c", buf[i]);
	}
	
	fclose(fp);
}
int main()
{
	// 按字节写入文件
	myFputc();
	return 0;
}

读文件

#include <stdio.h>
int fgetc(FILE * stream);
  • 功能:
    • 从stream指定的文件中读取一个字符
  • 参数:
    • stream:文件指针
  • 返回值:
    • 成功:返回读取到的字符
    • 失败:-1

示例代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int myFgetc()
{
	// 字符方式读文件
	char ch;
	FILE* fp = NULL;
	fp = fopen("test.txt", "r");
	while (1)
	{
		ch = fgetc(fp);
		//if(ch==EOF) // 判断文本文件结束符号,对二进制文件不能这样判断
		//  判断文件结束
		if (feof(fp) != 0) // 可以判断文本文件和二进制文件的结束符号
		{
			break;
		}
		// 输出读到的字符
		putchar(ch);
	}
	
	fclose(fp);
}

int main()
{
	myFgetc();
	return 0;
}

强化练习:实现vim、cat命令
myvim.c文件

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(int argc, char* argv[])
{
	// 判断是否有两个参数传进来
	if (argc != 2)
	{
		printf("用法:xxx.exe 文件名");
		return -1;
	}
	// 打开那个文件
	char* file_name = argv[1];
	// 声明一个写入字符的变量
	char ch;
	// 打开文件
	FILE* fp = NULL;
	fp = fopen(file_name, "w");
	// 判断是否打开文件成功
	if (fp == NULL)
	{
		perror("fopen");
		return -2;
	}
	// 将字符写入文件
	while (1)
	{
		// 获取写入字符
		ch = getchar();
		if (ch == ':')
		{
			ch = getchar();
			if (ch == 'w')
			{
				ch = getchar();
				if (ch == 'q')
				{
					break;
				}
			}
		}
		// 以字符写入文件
		fputc(ch, fp);
	}
	// 关闭文件
	fclose(fp);
	return 0;
}

mycat.c文件

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(int argc, char* argv[])
{
	if (argc != 2)
	{
		printf("用法:xxx.exe 文件名");
		return -1;
	}
	char* file_name = argv[1];
	char ch;
	FILE* fp = NULL;
	fp = fopen(file_name, "r");
	if (fp == NULL)
	{
		perror("fopen");
		return -2;
	}
	while (feof(fp) == 0)
	{
		ch = fgetc(fp);
		putchar(ch);
	}

	fclose(fp);
	return 0;
}

按照行读写文件fgets和fputs

写文件

#include <stdio.h>
int fputs(const char * str, FILE * stream);
  • 功能:
    • 将str所指定的字符串写入到stream指定的文件中,字符串结束符 ‘\0’ 不写入文件。
  • 参数:
    • str:字符串
    • stream:文件指针
  • 返回值:
    • 成功:0
    • 失败:-1
      示例代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int myFputs()
{
	char* buf[] = { "hello world\n","wang\n","lingling\n" };
	int n = sizeof(buf) / sizeof(buf[0]);
	// 打开文件
	FILE* fp = NULL;
	fp = fopen("test.txt", "w");
	if (fp == NULL)
	{
		perror("fopen");
		return -1;
	}
	// 按行写入到文件中
	for (int i = 0;i < n;i++)
	{
		fputs(buf[i], fp);
	}
	fclose(fp);
	return 0;
}

int main()
{
	myFputs();
	return 0;
}

读文件

#include <stdio.h>
char * fgets(char * str, int size, FILE * stream);
  • 功能:
    • 从stream指定的文件内读入字符,保存到str所指定的内存空间,
    • 直到出现换行字符、读到文件结尾或是已读了size - 1个字符为止,
    • 最后会自动加上字符 ‘\0’ 作为字符串结束。
  • 参数:
    • str:字符串
    • size:指定最大读取字符串的长度(size - 1)
    • stream:文件指针
  • 返回值:
    • 成功:成功读取的字符串
    • 读到文件尾或出错: NULL

示例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int myFgets()
{
	// 按照行读取文件
	char buf[100] = { 0 };
	FILE* fp = NULL;
	fp = fopen("test.txt", "r");
	// 失败返回-1
	if (fp == NULL)
	{
		perror("fopen");
		return -1;
	}
	// 成功,开始读取
	while (feof(fp) == 0)
	{
		// 空间初始化为0
		memset(buf, 0, sizeof(buf));
		fgets(buf, sizeof(buf), fp);
		printf("buf=%s\n", buf);
	}
	fclose(fp);
	return 0;
}
int main()
{
	myFgets();
	return 0;
}

强化练习: 文件版四则运算
有个文件大小不确定,每行内容都是一个四则运算表达式,还没有算出结果,写一个程序,自动算出其结果后修改文件。

1.生成目标文件代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

int bulidObj()
{
	// 1.目标生成a.txt文件,文件中每行都是 四则运算表达式,但是没有结果
	FILE* fp = NULL;
	fp = fopen("a.txt", "w");
	if (fp == NULL)
	{
		perror("fopen");
		return -1;
	}
	// 生成四则运算表达式 10*10=\n这种形式的
	// 产生一个随机数
	srand(time(NULL));
	// n行表达式
	int n = rand() % 20;
	char buf[100] = { 0 };
	// 定义两个int变量用来存取操作数
	int a, b;
	// 定义char变量用来存运算符“+ - * /”
	char ch;
	char opt[4] = { '+','-','*','/' };
	for (int i = 0;i < n;i++)
	{
		a = rand() % 100;
		b = rand() % 100;
		ch = opt[rand() % 4];
		// 指定格式输出到数组中
		sprintf(buf, "%d%c%d=\n", a, ch, b);
		// 使用fputs写入文件
		fputs(buf, fp);
	}
	fclose(fp);
	return 0;
}

int main()
{
	bulidObj();
	return 0;
}

2.算出结果重新写入到文件代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
int sumObj()
{
	char buf[100] = { 0 };
	// 1.逐行读取文件数据
	FILE* fp = NULL;
	fp = fopen("a.txt", "r");
	if (fp == NULL)
	{
		perror("fopen");
		return -1;
	}
	int a, b;
	char ch;
	int s=0;
	int n = 0;
	// 将读取完算出结果的数据存储到sbuf中
	char sbuf[20][100] = {0};
	while (feof(fp) == 0)
	{
		memset(buf, 0, sizeof(buf));
		fgets(buf, sizeof(buf), fp);
		// 如果读取到最后一行,直接跳过
		if (strlen(buf) == 0)
			break;
		//puts(buf);
		// 获取四则运算符表达式,生成结果
		// 指定格式提取数组数据
		sscanf(buf, "%d%c%d=", &a, &ch, &b);
		switch (ch)
		{
		case '+':
			s = a + b;
			break;
		case '-':
			s = a - b;
			break;
		case '*':
			s = a * b;
			break;
		case '/':
			s = a / b;
			break;
		}
		sprintf(sbuf[n], "%d%c%d=%d\n", a, ch, b, s);
		n++;
	}
	fclose(fp);
	// 3.生成的四则运算表达式和结果写入文件
	fp = fopen("a.txt", "w");
	if (fp == NULL)
	{
		perror("fopen");
		return -2;
	}
	for (int i = 0;i < n;i++)
	{
		fputs(sbuf[i], fp);
	}
	fclose(fp);
	return 0;
}
int main()
{
	//bulidObj();
	sumObj();
	return 0;
}

按照格式化文件fprintf、fscanf

写文件

#include <stdio.h>
int fprintf(FILE * stream, const char * format, ...);
  • 功能:
    • 根据参数format字符串来转换并格式化数据,然后将结果输出到stream指定的文件中,指定出现字符串结束符 ‘\0’ 为止。
  • 参数:
    • stream:已经打开的文件
    • format:字符串格式,用法和printf()一样
  • 返回值:
    • 成功:实际写入文件的字符个数
    • 失败:-1
      示例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int myFprintf()
{
	FILE* fp = NULL;
	fp = fopen("a.txt", "w");
	if (fp == NULL)
	{
		perror("fopen");
		return -1;
	}
	int num = fprintf(fp, "%d %d %d", 10, 20, 30);
	printf("%d\n", num);
	fclose(fp);
	return 0;
}

int main()
{
	myFprintf();
	return 0;
}

读文件

#include <stdio.h>
int fscanf(FILE * stream, const char * format, ...);
  • 功能:
    • 从stream指定的文件读取字符串,并根据参数format字符串来转换并格式化数据。
  • 参数:
    • stream:已经打开的文件
    • format:字符串格式,用法和scanf()一样
  • 返回值:
    • 成功:参数数目,成功转换的值的个数
    • 失败: - 1
      示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int myFscanf()
{
	FILE* fp = NULL;
	fp = fopen("a.txt", "r");
	if (fp == NULL)
	{
		perror("fopen");
		return -1;
	}
	int a = 0, b = 0, c = 0;
	int num = fscanf(fp, "%d %d %d", &a, &b, &c);
	printf("%d\n", num);
	printf("a=%d b=%d c=%d", a, b, c);
	fclose(fp);
	return 0;
	
}
int main()
{
	//myFprintf();
	myFscanf();
	return 0;
}

文件版排序(示例)
1.生成一个随机数文本

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int fileSort()
{
	FILE* fp = NULL;
	fp = fopen("b.txt", "w");
	if (fp == NULL)
	{
		perror("fopen");
		return -1;
	}
	srand(time(NULL));
	for (int i = 0;i < 10;i++)
	{
		int num = rand() % 200;
		fprintf(fp, "%d\n", num);
	}
	fclose(fp);
	return 0;
}
int main()
{
	fileSort();
	return 0;
}

2.对文件里随机生成的数字进行排序

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// 按照指定格式写入文件函数
int myWriteFile()
{
	FILE* fp = NULL;
	fp = fopen("b.txt", "w");
	if (fp == NULL)
	{
		perror("fopen");
		return -1;
	}
	int buf[10] = { 0 };
	int n = sizeof(buf) / sizeof(buf[0]);
	for (int i = 0;i < n;i++)
	{
		fprintf(fp, "%d\n", buf[i]);
	}
	fclose(fp);
}
int mySort()
{
	// 1.先用只读的方式把文件内容获取到
	FILE* fp = NULL;
	fp = fopen("b.txt", "r");
	if (fp == NULL)
	{
		perror("fopen");
		return -1;
	}
	int num = 0;
	//定义一个数组,用来存取读出来的数据
	int buf[10] = { 0 };
	int n = 0;
	while (feof(fp) == 0)
	{
		fscanf(fp, "%d\n", &num);
		//printf("%d\n", num);
		buf[n] = num;
		n++;
	}
	fclose(fp);
	// 2.对数组进行排序
	for (int i = 0;i < n-1;i++) //冒泡排序的个数
	{
		for (int j = 0;j < n - 1 - i;j++) // 冒一个泡要比较的次数
		{
			if (buf[j] > buf[j+1])
			{
				int tmp = buf[j];
				buf[j] = buf[j+1];
				buf[j+1] = tmp;
			}
		}
	}
	
	// 3.把排序后的数据写会文件中
	myWriteFile();
	return 0;
}
int main()
{
	mySort();
	return 0;
}

按照块读写文件fread和fwrite

写文件

#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
  • 功能:
    • 以数据块的方式给文件写入内容
  • 参数:
    • ptr:准备写入文件数据的地址
    • size: size_t 为 unsigned int类型,此参数指定写入文件内容的块数据大小
    • nmemb:写入文件的块数,写入文件数据总大小为:size * nmemb
    • stream:已经打开的文件指针
  • 返回值:
    • 成功:实际成功写入文件数据的块数目,此值和 nmemb 相等
    • 失败:0

示例


// 定义一个学生结构体
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct stu
{
	char name[50];
	int id;
}STU;
int blockFwrite()
{
	STU s[3] = { 0 };
	for (int i = 0;i < 3;i++)
	{
		sprintf(s[i].name, "stu100%d", i);
		s[i].id = i + 1;
	}
	FILE* fp = NULL;
	fp = fopen("c.txt", "wb");
	if (fp == NULL)
	{
		printf("fopen");
		return -1;
	}
	// 块操作写文件
	int ret = 0;
	ret = fwrite(s, sizeof(STU), 3, fp);
	printf("%d\n", ret);
	fclose(fp);
	return 0;
}
int main()
{
	blockFwrite();
	return 0;
}

读文件

#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
  • 功能:以数据块的方式从文件中读取内容
  • 参数:
    • ptr:存放读取出来数据的内存空间
    • size: size_t 为 unsigned int类型,此参数指定读取文件内容的块数据大小
    • nmemb:读取文件的块数,读取文件数据总大小为:size * nmemb
    • stream:已经打开的文件指针
  • 返回值:
    • 成功:实际成功读取到内容的块数,如果此值比nmemb小,但大于0,说明读到文件的结尾。
    • 失败:0

示例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct stu
{
	char name[50];
	int id;
}STU;

int blockFread()
{
	FILE* fp = NULL;
	fp = fopen("c.txt", "rb");
	if (fp == NULL)
	{
		printf("fopen");
		return -1;
	}
	STU s2[3] = {0};
	fread(s2, sizeof(STU), 3, fp);
	for (int i = 0;i < 3;i++)
	{
		printf("s2:%s,%d\n", s2[i].name, s2[i].id);
	}
	fclose(fp);
	return 0;
}

int main()
{
	blockFread();
	return 0;
}

强化训练:大文件拷贝
前提:需要设置两个命令行参数,设置方法->点击项目右键属性->调试->命令行参数->编辑->设置为123.mp4(这个文件你的项目目录中必须要有) 321.mp4(这个文件可以没有,没有会自己新建一个.mp4的文件)
图片解析
在这里插入图片描述
代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char* argv[])
{
	if (argc != 3)
	{
		printf("用法错误:xxx.exe 源文件 目标文件\n");
	}
	// 命令行指定源文件命令行参数,我这里默认以123.mp4为例
	char* src_file = argv[1];
	// 命令行指定目标文件命令行参数,我这里默认以321.mp4为例
	char* dest_file = argv[2];
	// 定义两个文件指针
	FILE* fpw = NULL, * fpr = NULL;
	// 以二进制只读的方式打开源文件
	fpr = fopen(src_file, "rb");
	if (fpr == NULL)
	{
		perror("src_fopen");
		return -1;
	}
	// 以二进制只读的方式打开目标文件
	fpw = fopen(dest_file, "wb");
	if (fpw == NULL)
	{
		perror("dest_fopen");
		fclose(fpr);
		return -1;
	}
	// 向堆区申请一块空间用来存放读取的数据,并将数据写入到目标文件,完成拷贝
	char* str = (char*)malloc(1024 * 1024);
	int ret = 0;
	while (feof(fpr) == 0)
	{
		memset(str, 0, 1024 * 1024);
		ret = fread(str, 1, 1024 * 1024, fpr);
		fwrite(str, 1, ret, fpw);
	}
	free(str);
	fclose(fpr);
	fclose(fpw);
	return 0;
}

文件的随机读写

#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
  • 功能:移动文件流(文件光标)的读写位置。
  • 参数:
    • stream:已经打开的文件指针
    • offset:根据whence来移动的位移数(偏移量),可以是正数,也可以负数,如果正数,则相对于whence往右移动,如果是负数,则相对于whence往左移动。如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了文件末尾,再次写入时将增大文件尺寸。
    • whence:其取值如下:
      • SEEK_SET:从文件开头移动offset个字节
      • SEEK_CUR:从当前位置移动offset个字节
      • SEEK_END:从文件末尾移动offset个字节
  • 返回值:
    • 成功:0
    • 失败:-1
#include <stdio.h>
long ftell(FILE *stream);
  • 功能:获取文件流(文件光标)的读写位置。
  • 参数:
    • stream:已经打开的文件指针
  • 返回值:
    • 成功:当前文件流(文件光标)的读写位置
    • 失败:-1
#include <stdio.h>
void rewind(FILE *stream);
  • 功能:把文件流(文件光标)的读写位置移动到文件开头。
  • 参数:
    • stream:已经打开的文件指针
  • 返回值:
    • 无返回值

示例代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

typedef struct stu
{
	char name[50];
	int id;
}STU;
int main()
{
	// 打开文件
	FILE* fp = NULL;
	fp = fopen("c.txt", "rb");
	if (fp == NULL)
	{
		perror("fopen");
		return -1;
	}

	// 对文件进行一系列操作

	// 1.ftell获取文件指针当前文件光标
	int offset = ftell(fp);
	printf("文件当前偏移量:%d\n", offset);

	// 2.fseek移动文件光标,SEEK_SET从文件开头开始,移动2 * sizeof(STU)字节
	STU s3 = { 0 }, s[3] = {0};
	fseek(fp, 2 * sizeof(STU), SEEK_SET);
	offset = ftell(fp);
	printf("文件当前偏移量:%d\n", offset);

	int ret = fread(&s3, sizeof(STU), 1, fp);
	if (ret == 1)
	{
		printf("获取到的第三个结构体:name:%s,id:%d\n", s3.name, s3.id);
	}

	// 回到文件的开头
	//fseek(fp, 0, SEEK_SET);
	rewind(fp);
	fread(s, sizeof(STU), 3, fp);
	for (int i = 0;i < 3;i++)
	{
		printf("s[%d]:\nname:%s,id:%d\n", i, s[i].name, s[i].id);
	}
	// 关闭文件
	fclose(fp);
	return 0;
}

Windows和Linux文本文件区别

  • Windows下文本文件,写入’\n’时,系统会自动转换成’\r\n’,读取’\r\n’时,系统自动转换成’\n’
  • Linux下文本文件,写入什么,读取就是什么
  • Windows下二进制打开文件,写入什么,读取就是什么
    示例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
	if (argc != 2)
	{
		printf("用法:xxx.exe 文件名");
		return -1;
	}
	char* file_name = argv[1];
	// 打开文件
	FILE* fp = NULL;
	fp = fopen(file_name, "rb");
	if (fp == NULL)
	{
		perror("fopen");
		return -2;
	}

	// 对文件进行一系列操作
	char buf[1024] = { 0 };
	fread(buf, 1, 1024, fp);
	int len = 0;
	while (buf[len])
	{
		if (buf[len] == '\n')
		{
			if (buf[len - 1] == '\r')
			{
				printf("Windows Flies\n");
				break;
			}
			else
			{
				printf("Linux Flies\n");
				break;
			}
		}
		len++;
	}
	// 关闭文件
	fclose(fp);
	return 0;
}

获取文件状态

#include <sys/types.h>
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);
  • 功能:获取文件状态信息
  • 参数:
    • path:文件名
    • buf:保存文件信息的结构体
  • 返回值:
    • 成功:0
    • 失败-1

系统提供的stat结构体

struct stat {
	dev_t         st_dev;         //文件的设备编号
	ino_t         st_ino;          //节点
	mode_t        st_mode;   //文件的类型和存取的权限
	nlink_t       st_nlink;     //连到该文件的硬连接数目,刚建立的文件值为1
	uid_t         st_uid;         //用户ID
	gid_t         st_gid;         //组ID
	dev_t         st_rdev;      //(设备类型)若此文件为设备文件,则为其设备编号
	off_t         st_size;        //文件字节数(文件大小)
	unsigned long st_blksize;   //块大小(文件系统的I/O 缓冲区大小)
	unsigned long st_blocks;    //块数
	time_t        st_atime;     //最后一次访问时间
	time_t        st_mtime;    //最后一次修改时间
	time_t        st_ctime;     //最后一次改变时间(指属性)
};

示例

#include <sys/types.h>
#include <sys/stat.h>

int main(int argc, char* argv[])
{
	if (argc != 2)
	{
		printf("用法:xxx.exe 文件名");
		return -1;
	}
	char* file_name = argv[1];
	struct stat s = { 0 };
	// 查看文件状态
	stat(file_name, &s);
	printf("文件大小:%d\n", s.st_size);
	return 0;
}

删除文件、重命名文件

#include <stdio.h>
int remove(const char *pathname);
  • 功能:删除文件
  • 参数:
    • pathname:文件名
  • 返回值:
    • 成功:0
    • 失败:-1
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
  • 功能:把oldpath的文件名改为newpath
  • 参数:
    • oldpath:旧文件名
    • newpath:新文件名
  • 返回值:
    • 成功:0
    • 失败: - 1

示例代码

#include <stdio.h>

int main(int argc, char* argv[])
{
	//if (argc != 2)
	//{
	//	printf("用法:xxx.exe 文件名\n");
	//	return -1;
	//}
	// 删除文件
	//remove(argv[1]);
	// 重命命名文件
	if (argc != 3)
	{
		printf("用法:xxx.exe 旧的文件名 新的文件名\n");
		return -1;
	}
	rename(argv[1], argv[2]);

	return 0;
}

文件的缓冲区

  • 文件缓冲区:实际文本读写操作,都是基于缓冲区操作。只有关闭文件或者缓冲区满了或者程序结束,缓冲区数据才会写入到文件。
  • 磁盘文件的存取:
  • 更新缓冲区:
#include <stdio.h>
int fflush(FILE *stream);
功能:更新缓冲区,让缓冲区的数据立马写到文件中。
参数:
stream:文件指针
返回值:
成功:0
失败:-1

磁盘文件存取示意图
在这里插入图片描述
示例代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	// 打开文件
	FILE* fp = NULL;
	fp = fopen("demo.txt","w");
	if (fp == NULL)
	{
		perror("fopen");
		return -1;
	}
	// 对文件进行操作
	fputs("hello world", fp);

	// 刷新缓冲区,写入文件
	fflush(fp);

	// 写一个死循环测试文件实际存到了缓冲区,并不是直接写入到了文件中
	while (1)
	{

	}
	// 关闭文件
	fclose(fp);
	return 0;
}

总结

| 文件操作函数  |头文件                                       | 函数原型                                                     |
| -------------|--------------------------------------------| ------------------------------------------------------------|
| fopen()      |                                 | FILE* fopen(const char* filename,const char* mode);                    
| fclose()     |                                 | int fclose(FILE * stream);                                   
| fputc()      |                                 | int fputc(int ch, FILE * stream);                            
| fgetc()      |                                 | int fgetc(FILE * stream);                                    
| fputs()      |                                 | int fputs(const char * str, FILE * stream);                  
| fgets()      |                                 | char * fgets(char * str, int size, FILE * stream);           
| fprintf()    |                                 | int fprintf(FILE * stream, const char * format, ...);        
| fscanf()     |  #include <stdio.h>             | int fscanf(FILE * stream, const char * format, ...);         
| fwrite()     |                                 | size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); 
| fread()      |                                 | size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 
| fseek()      |                                 | int fseek(FILE *stream, long offset, int whence);            
| ftell()      |                                 | long ftell(FILE *stream);                                    
| rewind()     |                                 | void rewind(FILE *stream);                                   
| remove()     |                                 | int remove(const char *pathname);                            
| rename()     |                                 | int rename(const char *oldpath, const char *newpath);        
| fflush()     |                                 | int fflush(FILE *stream);                                    
------------------------------------------------------------------------------------------------------------------
| stat()       | #include <sys/types.h>、 #include <sys/stat.h> | int stat(const char *path, struct stat *buf);                
  • 27
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值