C语言学习|文件处理

目录

前言

1. int main(int argc,char* argv[]) 中 argc 和 argv 的含义

argc

argv

验证代码

运行结果:

2. FILE*指针及其他流

FILE*

标准流

stdin

stdout

stdin和stderr的区别

3.文件处理的函数

fopen(文件路径,打开模式)

fseek(文件指针,偏移量,起始位置)

ftell(文件指针)

getc(文件指针)

putc(写入的字符,文件指针)

fclose(文件指针)

fprintf(文件指针,格式化字符串,...)

fscanf(文件指针,读取格式,储存地址)

fgets(字符串数组,读取字符数,文件指针)

fputs(字符串数组,文件指针)

fwrite(指针,每个元素的大小,写入个数,文件指针)

fread(指针,每个元素的大小,写入个数,文件指针)

feof(文件指针)

ferror(文件指针)


前言

本文部分内容理解较浅,但是如果是小白,可以对概念有个大致了解,如果要详细了解,请自行搜索研究。本文如果有地方错误,望大家多多为我批评指正(是不是太正式了?嘿嘿)

1. int main(int argc,char* argv[]) 中 argc 和 argv 的含义

argc

argc 全称是arguments count,表示传入参数的个数。如果没有传入任何参数,则argc为1

argv

argv 全称是arguments value,表示传入参数的值。argv中储存的是文件名或者文件路径

argv[0] = 程序本身的文件名或者文件路径

argv[1] = 第1个参数的文件名或者文件路径

argv[2] = 第2个参数的文件名或者文件路径

argv[argc] = null

验证代码

#include <stdio.h>

#define PRINT(X) printf(#X" = %s\n",X)

int main(int argc, char* argv[]) 
{
	printf("argc = %d\n", argc);
	PRINT(argv[0]);
	PRINT(argv[1]); //不管数目,看结果
	PRINT(argv[2]);
	PRINT(argv[3]);
}

运行结果:

直接运行

cmd窗口运行

2. FILE*指针及其他流

FILE*

FILE* 是指向文件的指针,可以通过FILE*来读取文件,是文件流,在文件读写期间,文件指针不会变

标准流

当一个用户进程被创建的时候,系统会自动为该进程创建三个数据流, 一个程序要运行,需要有输入、输出,如果出错,还要能表现出自身的错误。这是就要从某个地方读入数据、将数据输出到某个地方,这就够成了数据流。

因此,一个进程初期所拥有的这么三个数据流,就分别是标准输出、标准输入和标准错误,分别用stdout, stdin, stderr来表示。(转载自:https://blog.csdn.net/sxj731533730/article/details/73482361)

stdin

stdin 标准输入流,是FILE*的宏定义。大部分情况都是通过键盘输入的。scanf(),getchar()就是stdin流。

fscanf(stdin,"%s",str); //通过stdin流(键盘)输入到str中
scanf("%s",str); //与上面语句相同

stdout

stdout 标准输出流,是FILE*的宏定义。大部分通过显示屏输出。printf(),put(),就是通过stdout输出

fprintf(stdout,"ji ni tai mei"); //ji ni tai mei输出到屏幕中
printf("ji ni tai mei"); //与上面语句相同

stderr

 stderr 标准错误流,是FILE*的宏定义。通常是输出到屏幕上

FILE* fp = fopen("text.txt","r"); //以读模式打开根目录下的text.txt文件
if(fp==NULL)
{
    fprintf(stderr,"无法打开文件\n"); //将错误输出到屏幕中
}

stdin和stderr的区别

  • stdout主要处理使用输出,而stderr主要处理错误信息输出
  • stdout是行缓冲,输出会放在一个buff里面,只有到换行的时候才会输出到屏幕,而stderr是无缓冲的,会直接输出(linux环境才有)
  • stdout可以将输出重定向到某个文件上,而stderr不能将输出重定向,只能输出到控制台

注意: stdin stdout和stderr是文件指针的类型,也就是说可以传入带有文件指针类型的函数

3.文件处理的函数

fopen(文件路径,打开模式)

File* fopen(const char* filename,const char*mode)    (CPP)

fopen函数是打开文件的函数,且返回文件指针(FILE*),该函数声明包含在stdio.h里。第1个参数是文件路径,如果直接输入文件名称,得保证在与代码在同一个目录里,第2个参数是打开模式,可以通过读模式,写模式和更新模式打开文件

打开模式的参数参考(转 C primer plus 表13.1)

打开根目录下的demo.txt

FILE* fp = fopen("demo.txt","r"); //以读的方式,打开根目录下的demo.txt文件

r+读写前面的文字时,是替换对应字符

fseek(文件指针,偏移量,起始位置)

int fseek(FILE* stream,long int offset,int origin)

fseek()是移动文件指针,可以读取想要读取的位置。但在读文件时,文件指针的地址不发生变化。寻找模式有3种,开始位置(SEEK_SET),当前位置(SEEK_CUR),文件末尾(SEEK_END)。如果移动成功,则返回0,否则返回非0值。

起始位置

文件常量参考位置
SEEK_SET0文件开头
SEEK_CUR1当前指针位置
SEEK_END2文件末尾

fseek()移动文件指针在文件中的读取,但不改变文件指针

int main()
{
	FILE* fs = fopen("text.txt", "r");
	fseek(fs, 0L, SEEK_END); //将文件指针的指向移动到末尾
	printf("%p\n", fs);
	fseek(fs, 5L, SEEK_SET); //将文件指针的指向移动到开头,向前偏移5个字节
	printf("%p\n", fs);
	fseek(fs, 6L, SEEK_SET); //将文件指针的指向移动到开头,向前偏移6个字节
	printf("%p\n", fs);
	fseek(fs, -3L, SEEK_END); //将文件指针的指向移动到开头,向后偏移3个字节
	printf("%p\n", fs);
	fclose(fs);
	return 0;
}

 

 

ftell(文件指针)

long int ftell(FILE* stream)

ftell()返回当前文件指针的位置距离开头有多少个字节,也就是返回当前指针距离开头的位置

统计全文有多少字节

int main()
{
	FILE*fp = fopen("text.txt", "r"); //text文本中有abcde
	fseek(fp, 0L, SEEK_END); //将指针指向移动到文件末尾
	int count = ftell(fp); //返回末尾距离开头有多少字节
	printf("%d",count);  //返回5 正确
	fclose(fp);
	return 0;
}

getc(文件指针)

int getc(FILE* stream)

getc()是从文件中读取一个字符,与getchar()函数类似,使用getc需要传入文件指针

读取fp指针的字符

int ch = getc(fp) 

putc(写入的字符,文件指针)

int putc(int character, FILE* stream)

putc()是将字符写入到指定的文件指针中,也可以直接打印到屏幕上

putc(ch,fp); //将ch写入到fp中
putc(ch,stdout); //将ch打印到屏幕上

fclose(文件指针)

int fclose(FILE* stream)

fclose()是文件指针关闭指定的文件。如果成功关闭,fclose会返回0,否则返回EOF(-1)

检测文件是否关闭成功

FILE* fp = fopen("text.txt","r");
if(fclose(fp)!=0)
{
    fprintf(stderr,"无法关闭文件");
    exit(1);
}

fprintf(文件指针,格式化字符串,...)

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

fprintf() 流输出函数,将格式化字符串输出到对应流中。和printf()函数相似,printf()就是fprintf(stdout,...)

将文字输出到文件text.txt中

FILE* fp = fopen("text.txt","a+"); //在文件末尾添加
fprintf(fp,"ji ni tai mei %s","cai xu kun"); //将格式化字符串输出到fp文件流中

fprintf()和printf()区别

printf("wo shi shuai bi\n"); //printf和下面语句作用相同,是stdout
fprintf(stdout,"wo shi shuai bi\n"); 

fscanf(文件指针,读取格式,储存地址)

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

fscanf() 流输入函数,从stream中读入数据,将结果储存到对应地址中。scanf就是fscanf(stdin,),标准输入

 从文件读入数据,存储到字符串str中

char str[30] = {0};
FILE* fp = fopen("text.txt","r")
fscanf(fp,"%s",str); //从fp中读入字符串存储到str中

fgets(字符串数组,读取字符数,文件指针)

char* fgets(char* str,int num,FILE* stream)

fgets()是从文件流中按字节个数读字符,存储到str中。fgets()可以存储换行符。读入n个字符时,fgets只会存储n-1个字符,fgets()函数会自动填充空字符。fgets在读取成功时会返回传入数组的地址,而读取失败或读取到EOF时,返回NULL。注意fgets()是行缓冲,碰到文本文件中的换行符,会完成一次读操作

按行读取文本

int main()
{
	int n = 0; //行号
	char str_buffer[256] = { 0 }; //假设每行字符不超过256个
	FILE* fp = fopen("text.txt", "r");
	while (fgets(str_buffer, 256, fp) != NULL) //按行读取,fgets遇到换行符就停止读,进行输出
	{
		n++;
		printf(">%d<  %s", n,str_buffer);
	}
	fclose(fp);
	return 0;
}

fputs(字符串数组,文件指针)

int fputs(char*str,FILE* stream)

fputs()是将str输出到对应的文件流中,和puts()不同,它不会在末尾添加换行符,而fgets()可以存储换行符,因此fputs()和fgets()搭配很好。对于返回值,如果输出成功返回非0值,输出失败返回负数。fgets和fputs搭配使用。

fwrite(指针,每个元素的大小,写入个数,文件指针)

size_t fwrite(vod* ptr,size_t size,size_t count,FILE* stream)

fwrite()是将数组或者变量写入文件中,fwrite可以支持二进制写入,也支持文本,写入后,fwrite会返回成功写入的数量,可以通过此检测写入操作是否异常

txt文件不支持二进制,强制写入会乱码

//尝试将二进制数写入txt文件中
int main()
{
	FILE* fp = fopen("text.txt", "w"); 
	double arr[5] = { 3.2,4.5,6.7,2.1,4.3 };
	printf("已写入 %d 个元素\n",fwrite(arr, sizeof(double), 5, fp)); 
	fclose(fp);
    return 0;
}

 

fread(指针,每个元素的大小,写入个数,文件指针)

size_t fread(vod* ptr,size_t size,size_t count,FILE* stream)

fread()将文件的数据存储到对应的地址中,fread可支持二进制读取(需要设置rb),也支持文本读取,读取后,fread会返回成功读取的数量,可以通过此检测读取是否异常

 读取二进制文件

int main()
{
	double arr1[5] = {0};
	FILE* fp = fopen("text.bin", "rb");   //要设置rb,设置r会部分乱码
	printf("已读取 %d 个元素\n",fread(arr1, sizeof(double), 5, fp));
	
	for (int i = 0; i < 5; i++)
	{
		printf("%.2f\n", arr1[i]);
	}
	fclose(fp);
	return 0;
}

 

读写函数的区别

以上函数是文件处理中常用的读写函数,可分为文本读写和二进制读写

只支持文本读写的函数有:getc()和putc()、fgets()和fputs()、fprintf()(fprint()函数打印的是格式化字符串)

支持文本读写也支持二进制读写的函数:fwrite()和fread,fscanf()(fscanf()也支持二进制读写)

feof(文件指针)

int feof(FILE* stream)

feof()检测文件进行读操作有没有读到文件末尾(碰到EOF)。碰到EOF,feof会返回1,其他情况返回0。同时需要注意,当文件指针读到文件结束EOF时,并没有立即返回1,而是等在读取1个字符才返回1

 feof读取EOF不会立即返回1

int main()
{
	FILE* fp = fopen("mylife.txt", "r");
	while (!feof(fp)) //当内部指针读到文件结束EOF时,没有立即返回1,而是再读取一个字符才会
	{
		char ch = getc(fp);
		printf("%d %c: \t%x\n",feof(fp), ch, ch); //读取到EOF,会返回1,如果没有读取到,则返回0
	}
	fclose(fp);
	return 0;
}

 可以看到最后一行出现了-1,是EOF的值,说明ch读取到EOF了,但是feof并没有返回1,而是下一次才返回了1,结束了循环。因此在使用feof读文件时,字符需要检测是不是EOF,再打印

代码改善

int main()
{
	FILE* fp = fopen("mylife.txt", "r");
    while (1)
	{
		char ch = getc(fp);
		if (feof(fp)) //将feof检测放到ch读取之后
			break;
		printf("%d %c: \t%x\n",feof(fp), ch, ch);
	}
    fclose(fp)
    return 0;
}

ferror(文件指针)

ferror(FILE* stream)

ferror()检测文件读取是否出现错误,如果有错误,则返回1,没有错误则返回0

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值