C语言:文件操作

文件操作
系统文件

标准输入:stdin,编号0,printf-标准输出
标准输出:stdout,编号1,scanf-标准输入
标准错误:stderr,编号2,perror-标准错误
应用程序启动时,自动被打开;程序执行结束时,自动被关闭

文件指针
  • 文件指针定义:FILE *fp;
  • 文件指针初始化:fp = fopen();
  • 操作文件:使用文件读写函数来完成,fputc,fgets,fputs,fgets,fread,fwrite等
文件分类
  • 设备文件
    屏幕、键盘、磁盘、网卡、声卡、显卡、扬声器等
  • 磁盘文件
    文本文件:字符表示数据
    二进制文件:字节表示数据
文件操作步骤
  1. 打开文件fopen()

FILE* fopen(const char* filename,const char* mode);
参数1-filename:待打开文件的文件名(访问路径)
参数2-mode:文件操作权限
返回值:成功返回打开文件的文件指针;失败返回NULL

1.mode
r/rb:以只读方式打开文件,若文件不存在则报错
w/wb:以写方式打开文件,若文件不存在则新建,若存在则清空
a/ab:以追加方式打开文件,若文件不存在则新建,若存在则在末尾追加内容
r+/rb+:以可读可写方式打开文件(不创建新文件)
w+/wb+:以可读可写方式打开文件(若文件不存在则新建,若存在则清空)
a+/ab+:以追加方式打开可读可写文件(若文件不存在则新建,若存在则在末尾追加内容)
2.b是二进制模式的意思,只在windows有效,linux上两种形式作用一样
3.linux下文件行尾以\n结尾,windows下文件行尾以\r\n结尾

  1. 读写文件

  2. 关闭文件fclose()

int fclose(FILE* stream);
参数1-stream:打开文件的文件指针(fopen的返回值)
返回值:成功0,失败-1

访问路径
1.相对路径
vs环境下
编译执行,文件相对路径是指相对于工程文件所在文件目录位置;
双击可执行文件执行,相对路径指相对于可执行文件所在目录位置。
2.绝对路径:从系统磁盘根盘符开始,到待访问文件的完整路径

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

int main(void)
{
	FILE* fp = NULL;
	//fp = fopen("F:/test/test.txt","r");
	fp = fopen("F:\\test\\test.txt","r");
	if (fp == NULL){
		perror("fopen error");
		return -1;
	}
	fclose(fp);
	return 0;
}
文件操作函数
  • 按字符写文件fputc

int fputc(int ch,FILE* stream);
参数1-ch:待写入的字符
参数2-stream:打开文件的fp
返回值:写入成功返回写入字符的ascii码,失败返回-1

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

int main02() {
	FILE* fp = fopen("F:/test/test.txt","w");
	if (fp == NULL) {
		perror("fopen error");
		return -1;
	}
	for (size_t i = 0; i < 26; i++)
	{
		char ch = fputc('a'+i, fp);
		if (ch == -1) {
			perror("fputc error");
			return -1;
		}
		printf("%c", ch);
	}
	
	
	fclose(fp);
	return 0;
}
  • 按字符读文件fgetc

int fgetc(FILE* stream);
参数:待读取的文件指针
返回值:成功返回读取到的字符的ascii,失败返回-1;

文本文件的结束标记:EOF(-1)

void read_file() {
	FILE* fp = fopen("F:/test/test.txt", "r");
	if (fp == NULL) {
		perror("fopen error");
		return;
	}
	char ch = fgetc(fp);
	while (ch != -1) {
		printf("%c ", ch);
		ch = fgetc(fp);
	}
	fclose(fp);
}
  • feof

int feof(FILE* stream);
函数作用:判断是否到达文件结尾
参数:fopen返回值
返回值:到达文件结尾返回非0【真】,没有到达文件结尾返回0【假】

文本文件由ascii组成,asciima范围是0~127,正文不会出现-1,所以可以用EOF(-1)判断是否到达结尾;二进制文件正文可能会存在-1,可以使用feof判断是否到达文件结尾。

void read_file() {
	FILE* fp = fopen("F:/test/test.txt", "r");
	if (fp == NULL) {
		perror("fopen error");
		return;
	}
	char ch = fgetc(fp);
	while (1) {
		if (feof(fp)) {
			break;
		}
		printf("%c ", ch);
		ch = fgetc(fp);
	}
	fclose(fp);
}
  • 按行读写文件

char* fgets(char* str,int size,FILE* stream);
函数功能:从stream指定文件读取字符串保存到str指定内存空间,直到出现换行或文件尾或已读size-1个字符为止,末尾自动添加’\0’
参数1-str:读取到的字符串
参数2-size:指定最大读取字符串长度(size-1)
参数3-stream:文件指针
返回值:成功返回读取到的字符串,读到文件尾或出错返回NULL

int fputs(const char* str,FILE* stream);
函数功能:将str指定的字符串写入到stream指定文件中,字符串’\0’不写入文件
参数1-str:字符串
参数2-stream:文件指针
返回值:成功0,失败-1

案例:获取键盘输入写入文件

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

int main(void)
{
	FILE* fp = fopen("F:/test/test.txt","a");
	if (fp == NULL) {
		perror("fopen error");
		return -1;
	}
	char buf[4096];
	while (1) {
		fgets(buf,4096,stdin);
		if (strcmp(buf, ":wq\n") == 0) {
			break;
		}
		fputs(buf, fp);
	}
	fclose(fp);
	return 0;
}
操作文本文件
  • fprintf():写指定格式内容到文件中

int fprintf(FILE* stream,const char* format,...);

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

int main(void)
{
	FILE* fp = fopen("F:/test/test03.c", "w");
	if (fp == NULL) {
		perror("fopen error");
		return -1;
	}
	fprintf(fp, "%d%c%d=%d\n", 10, '*', 7, 10 * 7);
	fclose(fp);
	return 0;
}
  • fscanf():

int fscanf(FILE* stream,const char* format,...);

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

int main() {
	FILE* fp = fopen("F:/test/test03.c", "r");
	if (fp == NULL) {
		perror("fopen error");
		return -1;
	}
	int a, b, c;
	char ch;
	fscanf(fp, "%d%c%d=%d\n", &a, &ch, &b, &c);
	printf("%d%c%d=%d\n", a, ch, b, c);
	fclose(fp);
	return 0;
}
操作二进制文件
  • fwrite():将数据写入文件

size_t fwrite(const void* ptr,size_t size,size_t nmemb,FILE* stream);
参数1-ptr:待写出数据的地址
参数2-size:待写出数据的大小
参数3-nmemb:写出次数(size*nmemb=写出数据总大小)
参数4-stream:文件
返回值:成功返回写入文件次数(参3的值),失败返回0

  • fread()从文件读取数据

size_t fread(const void* ptr,size_t size,size_t nmemb,FILE* stream);
参数1-ptr:读取出的数据的存储的地址
参数2-size:一次读取字节数
参数3-nmemb:读取次数(size*nmemb=读出数据总大小)
参数4-stream:文件
返回值:成功返回读取文件次数(参3的值),失败返回0

随机位置读

文件读写指针,一个文件内只有一个

  • fseek():修改文件指针位置

int fseek(FILE* stream,long offset,int whence);
参数1-stream:文件
参数2-offset:偏移量(+向后,-向前)
参数3-whence:SEEK_SET(文件开头),SEEK_CUR(文件当前位置),SEEK_END(文件结尾位置)
返回值:成功0,失败-1

  • ftell():获取文件读写指针位置

long ftell(FILE* stream);
返回值:从文件当前读写位置到起始位置的偏移量

  • rewind():把文件读写指针重置到文件开头

void rewind(FILE* stream);

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

int main() {
	FILE* fp = fopen("F:/test/test08.txt", "r+");
	if (fp == NULL) {
		perror("fopen error");
	}
	char buf[6];
	fputs("111112222233333", fp);
	rewind(fp);//文件读写指针为同一个,不重置指针会继续往后读取数据,从而造成读不到数据的结果;也可通过fseek修改文件指针位置
	fgets(buf, 6, fp);
	printf("buf = %s", buf);
	fclose(fp);
	return 0;
}
linux和windows文件区别
  1. 对于二进制文件操作,windows下模式要添加"b",linux下二进制和文本文件打开文件模式没有区别
  2. windows下回车是\r,换行是\n,一行结尾的字符是\r\n;linux下回车换行是\n,一行结尾是\n
  3. 对文件指针,先写后读,windows和linux效果一致;先读后写,windows下需要在写操作之前使用fseek(fp,0,SEEK_CUR)使文件读写指针生效,linux无效修改可直接进行写操作
#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

int main(void)
{
	FILE* fp = fopen("F:/test/test08.txt", "r+");
	if (fp == NULL) {
		perror("fopen error");
		return -1;
	}
	char buf[6] = {0};
	char* ptr = fgets(buf, 6, fp);
	
	printf("buf=%s,ptr=%s\n", buf,ptr);
	fseek(fp, 0, SEEK_CUR);//windows下先读后写的写操作前需要使用该函数,linux下不需要使用,可以直接进行写入
	int ret = fputs("AAAAA", fp);
	printf("ret=%d\n", ret);

	fclose(fp);
	return 0;
}
获取文件状态
  • 获取文件状态

int stat(const char* path,struct stat* buf);
参数1-path:访问文件路径
参数2-buf:文件属性结构体
返回值:成功0,失败-1

使用该函数需要使用头文件:

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 
#include
#include

int main(void)
{
	struct stat buf;
	int ret = stat("F:/test/test08.txt", &buf);//传出参数:函数调用完毕时充当函数返回值
	printf("文件大小:%d\n", buf.st_size);
	return 0;
}
删除、重命名文件
  • 删除文件

int remove(const char* pathname);

  • 重命名文件

int rename(const char* oldpath,const char* new path);

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

int main() {
	//remove("F:/test/test07.txt");
	rename("F:/test/test05.txt", "F:/test/改名.txt");
	return 0;
}
缓冲区刷新

(缓输出)标准输出–stdout–标准输出缓存区:写给屏幕的数据,先输出到缓存区,由缓冲区一次性刷新到物理设备(屏幕)

(预读入)标准输入-- stdin–标准输入缓冲区:从键盘读取的数据直接读到缓冲区,由缓冲区给程序提供数据

行缓冲:printf(),遇到\n就会将缓冲区中的数据刷新到物理设备
全缓冲:文件,缓冲区存满数据刷新到物理设备
无缓冲:perror,缓冲区只要有数据就立即刷新到物理设备

自动刷新缓冲区:文件关闭时缓冲区会被自动刷新

手动刷新缓冲区:
int fflush(FILE* stream);
返回:成功0,失败-1

你可能感兴趣的:(c/c++学习笔记,c/c++)