一、C语言篇——10. 文件操作

本文详细介绍了C语言中文件的打开与关闭,包括不同模式的用法。接着讨论了文件的读写操作,如fgetc、fputc、fgets、fputs、fprintf、fscanf等函数的使用。还涵盖了文件指针的移动、文件大小获取、文件删除与重命名。最后提到了文件缓冲区的管理和fflush函数的应用。
摘要由CSDN通过智能技术生成

01. 文件打开和关闭

#include <stdio.h>
FILE * fopen(const char * filename, const char * mode);
功能:打开文件
参数:
	参1:需要打开的文件名,根据需要加上路径
	参2:打开文件的模式设置
返回值:
	成功:文件指针
	失败:NULL
打开模式含义
r或rb以只读方式打开文件。文件不存在,则报错
w或wb以写方式打开文件。文件存在,清空文件并打开,文件不存在,则创建该文件
a或ab以追加的方式打开文件,在末尾添加内容。文件不存在,创建文件
r+或rb+以读写方式打开文件,文件不存在,则报错
w+或wb+以读写方式打开文件,文件存在,清空文件并打开,文件不存在,则创建该文件
a+或ab+以追加的方式打开文件,在末尾添加内容。文件不存在,创建文件

注意:

  • b是二进制模式的意思,b只是在Windows有效,在Linux用r和rb的结果是一样的
  • Unix和Linux下所有的文本文件行都是\n结尾,而Windows所有的文本文件行都是\r\n结尾
  • 在Windows平台下,以“文本”方式打开文件,不加b:
    • 当读取文件的时候,系统会将所有的 “\r\n” 转换成 “\n”
    • 当写入文件的时候,系统会将 “\n” 转换成 “\r\n” 写入
    • 以"二进制"方式打开文件,则读\写都不会进行这样的转换
  • 在Unix/Linux平台下,“文本”与“二进制”模式没有区别,“\r\n” 作为两个字符原样输入输出
#include <stdio.h>
int fclose(FILE * stream);
功能:关闭先前fopen()打开的文件。此动作让缓冲区的数据写入文件中,并释放系统所提供的文件资源。
参数:文件指针
返回值:
	成功:0
	失败:-1
#include <stdio.h>

int main()
{
    FILE* fp = NULL;
    
    //打开文件
    fp = fopen("./test","w"); //以w写方式打开
    if(fp == NULL)
    {
        perror("open err"); //是标准出错打印函数,能打印调用库函数出错原因
        return -1;
    }
    
    //关闭文件
    fclose(fp);
    
    return 0;
}

02. 文件的读写操作

按照字符读写文件fgetc、fputc

fputc()函数

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

在C语言中,EOF表示文件结束符(end of file)。这种以EOF作为文件结束标志的文件,必须是文本文件。

feof()函数既可用以判断二进制文件又可用以判断文本文件

int feof(FILE * stream);
功能:检测是否读取到了文件结尾。判断的是最后一次“读操作的内容”,不是当前位置内容(上一个内容)。
参数:文件指针
返回值:
	非0值:已经到文件结尾
	0:没有到文件结尾

fgetc()函数

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

int main()
{
    //打开文件
    FILE *fp = fopen("./test","w+");
    if(fp == NULL)
    {
        perror("open err");
        return -1;
    }
    
    //写文件
    char buf[] = "this is a test for fputc";
	int i = 0;
	int n = strlen(buf);
	for (i = 0; i < n; i++)
	{
		//往文件fp写入字符buf[i]
		int ch = fputc(buf[i], fp);
		printf("ch = %c\n", ch);
	}
    
    //读文件
    char ch;
    while(!feof(fp))
    {
        ch = fgetc(fp);
        printf("%c",ch);
    }
    
    //关闭文件
    fclose(fp);
    
    return 0;
}

按照行读写文件fgets、fputs

fputs()函数

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

fgets()函数

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

int main()
{
    FILE *fp = fopen("./test","w+");
    if(fp == NULL)
    {
        perror("fopen err");
        return -1;
    }
    
    //写文件
    char *buf[] = { "123456\n", "bbbbbbbbbb\n", "ccccccccccc\n" };
	int i = 0;
	int n = 3;
	for (i = 0; i < n; i++)
	{
		int len = fputs(buf[i], fp);
		printf("len = %d\n", len);
	}
    
    //读文件
    char buf[100] = 0;

	while (!feof(fp)) //文件没有结束
	{
		memset(buf, 0, sizeof(buf));
		char *p = fgets(buf, sizeof(buf), fp);
		if (p != NULL)
		{
			printf("buf = %s", buf);
		}
	}
    
    fclose(fp);
    
	return 0;
}

按照格式化文件fprintf、fscanf

fprintf()函数

int fprintf(FILE * stream, const char * format, ...);
功能:根据参数format字符串来转换并格式化数据,然后将结果输出到stream指定的文件中,指定出现字符串结束符 '\0'  为止。
参数:
	参1:文件指针
	参2:字符串格式,用法和printf()一样
返回值:
	成功:实际写入文件的字符个数
	失败:-1

fscanf()函数

#include <stdio.h>
int fscanf(FILE * stream, const char * format, ...);
功能:从stream指定的文件读取字符串,并根据参数format字符串来转换并格式化数据。
参数:
	参1:文件指针
	参2:字符串格式,用法和scanf()一样
返回值:
	成功:参数数目,成功转换的值的个数
	失败: - 1
#include <stdio.h>

int main()
{
    FILE *fp = fopen("./test","w+");
    if(fp == NULL)
    {
        perror("fopen err");
        return -1;
    }
    
    //写文件
    fprintf(fp, "%d %d %d\n", 1, 2, 3);
    
    //读文件
    int a = 0;
	int b = 0;
	int c = 0;
	fscanf(fp, "%d %d %d\n", &a, &b, &c);
	printf("a = %d, b = %d, c = %d\n", a, b, c);
    
    fclose(fp);
    
    return 0;
}

按照块读写文件fread、fwrite

fwrite()函数

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

fread()函数

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:以数据块的方式从文件中读取内容
参数:
	参1:存放读取出来数据的内存空间
	参2: size_t 为 unsigned int类型,此参数指定读取文件内容的块数据大小
	参3:读取文件的块数,读取文件数据总大小为:size * nmemb
	参4:已经打开的文件指针
返回值:
	成功:实际成功读取到内容的块数,如果此值比nmemb小,但大于0,说明读到文件的结尾。
	失败:0
//写文件
typedef struct Stu
{
	char name[50];
	int id;
}Stu;

Stu s[3];
int i = 0;
for (i = 0; i < 3; i++)
{
	sprintf(s[i].name, "stu%d%d%d", i, i, i);
	s[i].id = i + 1;
}

int ret = fwrite(s, sizeof(Stu), 3, fp);
printf("ret = %d\n", ret);

//读文件
typedef struct Stu
{
	char name[50];
	int id;
}Stu;

Stu s[3];
int ret = fread(s, sizeof(Stu), 3, fp);
printf("ret = %d\n", ret);

int i = 0;
for (i = 0; i < 3; i++)
{
	printf("s = %s, %d\n", s[i].name, s[i].id);
}

03. 随机位置读文件

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

fseek()函数

int fseek(FILE *stream, long offset, int whence);
作用:移动光标的读写位置
参数:
	参1:文件指针
	参2:偏移量(矢量  +向后   -向前)
	参3:
		SEEK_SET:从文件开头位置移动
		SEEK_CUR:从文件当前位置移动
		SEEK_END:从文件末尾位置移动
返回值:
	成功,0
	失败,-1

ftell()函数

long ftell(FILE* stream);
作用:获取光标的位置
参数:文件指针
返回值:
	成功,当前文件光标的读写位置
	失败,-1

作用:ftell() + fseek(SEEK_END),来获取文件大小。

rewind()函数

void rewind(FILE *stream);
功能:把文件光标的读写位置移动到文件开头
参数:文件指针
返回值:无返回值

测试fseek()、ftell()、rewind()

#include <stdio.h>

int main()
{
    //打开文件
    FILE *fp = fopen("test.txt","r");
    if(!fp)  // fp == NULL
    {
        perror("fopen error");
        return -1;
    }
    
    //移动文件光标
    fseek(fp,-1,SEEK_END);  //从文件末尾开始,向前移动1个距离
    
    int a = ftell(fp);  //返回光标所在的位置
    
    rewind(fp);  //将光标移到到文件开头
    
    //关闭文件
    fclose(fp);
    
    return 0;
}

04. Windows和Linux文本文件的区别

  1. 对于二进制文件操作,Windows使用"b"。 Linux下二进制和文本没区别

  2. Windows下,回车\r、换行\n,\r\n 。Linux下回车换行都是\n

  3. 对文件指针,先写后读,Windows和Linux效果一致。

    先读后写,Windows下需要使用fseek(fp,0,SEEK_CUR)来获取文件光标,才生效。Linux下无需修改

05. 获取文件大小stat()

虽然可以通过fseek(fp,0,SEEK_END) + ftell(fp)获取文件大小,但是打开文件对于系统而言,系统的资源消耗较大。所以可以用stat()函数来获取文件大小

int stat(const char* path,struct stat *buf);
功能:获取文件状态信息
参数:
	参1:访问文件的路径或文件名
	参2:保存文件信息的结构体
返回值:
	成功,0
	失败,-1

stat结构体原型(Linux系统下)

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;     //最后一次改变时间(指属性)
};

stat()测试

#include <sys/types.h>  //stat()函数用到的头文件
#include <sys/stat.h>  //stat()函数用到的头文件
#include <stdio.h>

int main()
{
	struct stat st = { 0 };
    
    int ret = stat("test.txt",&st); //传出参数:在函数调用结束时,充当函数的返回值
    int fp_size = st.st_size; //不打开文件获取文件大小
    printf("文件大小为:%d",fp_size);
    
	return 0;
}

06. 删除文件remove()、重命名文件rename()

remove()函数

int remove(const char *pathname);
功能:删除文件
参数:文件名
返回值:
	成功,0
	失败,-1

rename()函数

int rename(const char *oldpath, const char *newpath);
功能:把oldpath的文件名改为newpath
参数:
	参1:旧文件名
	参2:新文件名
返回值:
	成功,0
	失败,-1

07. 文件缓冲区fflush()

标准输出 —— stdout —— 标准输出缓冲区。写给屏幕的数据,都是先存缓冲区,有缓冲区一次性刷新到物理设备(屏幕)

标准输入 —— stdin —— 标准输入缓冲区。从键盘读取的数据,直接读到缓冲区中,由缓冲区给程序提供数据。

简称:预读入、缓输出。

行缓冲:如printf(),遇到\n就会将缓冲区中的数据刷新到物理设备

全缓冲:如文件操作,缓冲区存满,数据刷新到物理设备上

无缓冲:如perror(),缓冲区中只要有错误(数据),就立即刷新到屋里设备

fflush()函数:手动刷新缓冲区

int fflush(FILE *stream);
功能:更新缓冲区,让缓冲区的数据立马写到文件中。
参数:文件指针
返回值:
	成功,0
	失败,-1

ffulsh()函数的使用

#include <stdio.h>
int main()
{
    FILE *fp = fopen("test.txt","w+");
    if(!fp)
    {
        perror("fopen error");
        return -1;
    }
    
    char c = 0;
    while(1)
    {
        scanf("%c",&c);
        if(m == ':') //用户如果输入":" 则退出
        {
            break;
        }
        fputc(c,fp);  //不是":",输入文件中去
        fflush(fp);  //手动刷新文件缓冲区到物理磁盘中,如果没有此函数,则当文件关闭时,才会自动刷新缓冲区。
    }
    
    //当文件关闭时,才会自动刷新缓冲区
    fclose(fp);
    
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值