文件操作
文件
计算机文件(或称文件、电脑档案、档案),是存储在某种长期存储设备或临时存储设备中的一段数据流,并且归属于计算机文件系统管理之下。
- 长期存储设备:一般指磁盘、光盘、磁带等
- 短期存储设备:一般指计算机内存
注:存储于长期存储设备的文件不一定是长期存储的,有些也可能是程序或系统运行中产生的临时数据,并于程序或系统退出后删除。
文件是什么?
.exe .txt .ppt .jpg .mp4 .avi
文本文件和二进制文件
- 文本文件:由一些字符的序列组成的
文本文件无非是用最简单的方式可以读写的文件
- more、tail
- cat
- vi
- 二进制文件:除文本文件以外的文件
- 二进制文件是需要专门的程序来读写的文件
文件输入输出
- 用>和<做重定向
FILE
- FILE* fopen(const char * restrict path,const char * restrict mode);
- int fclose(FILE *stream)
- fscanf(FILE*,…)
- fprintf(FILE*,…)
fopen函数(打开文件)
fopen 函数用于打开一个文件并返回文件指针。
打开文件的标准代码
FILE* fp = fopen("file","r");
if(fp){
fscanf(fp,...);
fclose(fp);
}else{
...
}
函数原型
#include <stdio.h>
...
FILE *fopen(const char *path, const char *mode);
返回值
- 如果文件打开成功,则返回一个指向 FILE 结构的文件指针;
- 如果文件打开失败,则返回 NULL 并设置 errno 为指定的错误。
注:
- path 参数可以是相对路径(…/fishc.txt)也可以是绝对路径(/home/FishC/fishc.txt),如果只给出文件名而不包含路径,则表示该文件在当前文件夹中
- 从本质上来说,文本文件也是属于二进制文件的,只不过它存放的是相应的字符编码值。
- 打开方式要区分文本模式和二进制模式的原因,主要是因为换行符的问题。C 语言用 \n 表示换行符,Unix 系统用 \n,Windows 系统用 \r\n,Mac 系统则用 \r。如果在 Windows 系统上以文本模式打开一个文件,从文件读到的 \r\n 将会自动转换成 \n,而写入文件则将 \n 替换为 \r\n。但如果以二进制模式打开则不会做这样的转换。Unix 系统的换行符跟 C 语言是一致的,所以不管以文本模式打开还是二进制模式打开,结果都是一样的。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
int ch;
if((fp = fopen("hello.txt","r"))== NULL)
{
printf("打开文件失败!\n");
exit(EXIT_FAILURE);
}
while((ch = getc(fp))!= EOF)
{
putchar(ch);
}
fclose(fp);
return 0;
}
fgetc函数(单个字符的读取)
fgetc函数用于从文件流中读取下一个字符并推进文件的位置指示器(用来指示接下来要读写的下一个字符的位置)
函数原型
#include <stdio.h>
...
int fgetc(FILE *stream);
参数解析
stream:该参数是一个FILE对象的指针,指定一个待读取的文件流
返回值
- 该函数将读取的unsigned char类型转换为int类型并返回
- 如果文件结束或者遇到错误,则返回EOF
注:
- fgetc函数和getc函数区别:
fgetc是一个函数
getc是一个宏的实现 - 一般来说宏产生较大的代码,但是避免了函数调用的堆栈操作,速度较快
- getc是由宏实现的,对其参数可能有不止一次的调用。
fputc函数(单个字符的写入)
fputs 函数用于将一个字符串写入到指定的文件中,表示字符串结尾的 ‘\0’ 不会被一并写入。
函数原型
#include <stdio.h>
...
int fputs(const char *s, FILE *stream);
返回值
- 如果函数调用成功,返回一个非 0 值;
- 如果函数调用失败,返回 EOF。
注:
- fputc和putc区别:
fputc是一个函数
putc是一个宏的实现 - 一般来说宏产生较大的代码,但是避免了函数调用的堆栈操作,速度较快
- getc是由宏实现的,对其参数可能有不止一次的调用。
fgets(读整个字符串)
fgets函数用于从指定文件中读取字符串。
fgets函数最多可以读取size-1个字符,因为结尾处会自动添加一个字符串结束符‘\0’。
当读取到换行符(‘\n’)或文件结束符(EOF)时,表示结束读取(‘\n’会被作为一个合法的字符读取)
函数原型
#include <stdio.h>
...
char *fgets(char *s,int size,FILE *stream);
参数解析
s:字符型指针,指向用于存放读取字符串的位置
size:指定读取的字符数(包含最后自动添加的‘\0’)
stream:该参数是一个FILE对象的指针,指定一个待操作的数据流
返回值
- 如果函数调用成功,返回s参数指向的地址。
- 如果在读取字符的过程中遇到EOF,则EOF指示器被设置
如果还没读入任何字符就遇到EOF,则s参数指向的位置保持原来的内容,函数返回NULL - 如果在读取的过程中发生错误,则error指示器被设置,函数返回NULL,但s参数指向的内容可能被改变。
fputs函数(写整个字符串)
fputs函数用于将一个字符串写入到指定的文件中,表示字符串结尾的‘\0’不会被一并写入。
函数原型
#include <stdio.h>
...
char *fputs(char *s,int size,FILE *stream);
参数解析
s:字符型指针,指向用于存放读取字符串的位置
stream:该参数是一个FILE对象的指针,指定一个待操作的数据流
返回值
- 如果函数调用成功,返回一个非0值
- 如果函数调用失败,返回EOF
fscanf函数(从文件中读取格式化输入)
fscanf 函数用于从指定文件中读取格式化字符串。
函数原型
#include <stdio.h>
...
int fscanf(FILE *stream, const char *format, ...);
参数解析
- stream 参数
该参数是一个 FILE 对象的指针,指定一个待操作的数据流。
- format 参数
format 参数是一个格式化字符串,由格式化占位符和普通字符组成。
该格式化字符串指定如何处理读取到的数据:
空白字符:该函数将读取并忽略空白字符(空白字符包含空格、回车和制表符);
除了格式占位符(% 开头)外的非空白字符:指定函数必须从输入流中读取到的字符,如果读取不匹配,则函数调用失败,并从匹配失败处截断输入流;
格式化占位符(% 开头):用于指明获取的数据类型及位置。
fprintf函数(格式化输出到文件)
fprintf 函数用于打印格式化字符串到指定的文件。
函数原型
#include <stdio.h>
...
int fprintf(FILE *stream, const char *format, ...);
参数解析
- stream 参数
该参数是一个 FILE 对象的指针,指定一个待操作的数据流。
- format 参数
format 参数是一个格式化字符串,由格式化占位符和普通字符组成。
格式化占位符(以 % 开头)用于指明输出的参数值如何格式化。
fread函数(从文件中读取数据)
fread 函数用于从指定的文件中读取指定尺寸的数据。
#include <stdio.h>
...
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数解析
ptr 指向存放数据的内存块指针,该内存块的尺寸最小应该是 size * nmemb 个字节
size 指定要读取的每个元素的尺寸,最终尺寸等于 size * nmemb
nmemb 指定要读取的元素个数,最终尺寸等于 size * nmemb
stream 该参数是一个 FILE 对象的指针,指定一个待读取的文件流
返回值
-
返回值是实际读取到的元素个数(nmemb);
-
如果返回值比 nmemb 参数的值小,表示可能读取到文件末尾或者有错误发生(可以使用 feof 函数或 ferror 函数进一步判断)。