Linux下的文件操作----高级文件操作
基于文件指针的文件操作,有缓冲区,是高级文件的操作,属于底层文件系统
一、fopen();文件打开、创建函数
FILE *fopen(const char *__restrict__ __filename, const char *__restrict__ __modes);
-
函数声明: FILE *fopen(const char *restrict __filename, const char *restrict __modes);
-
函数功能: 根据 __modes设定的读写方式,创建\打开文件
-
参数: 参数1: 文件路径名(可以是char*变量); 参数2: 文件读写方式;
-
返回值: 打开成功返回文件指针 打开失败返回NULL
modes的参数列表
对于打开文件所选择的操作方式来说,一经选择将不可改变,除非关闭文件后重新打开。
文本文件(ASCII) | |||
---|---|---|---|
模式 | 功能描述 | 文件读写位置 | 备注 |
“r” | 打开只读文件,文件必须存在,如果不存在则会报错。 | 从头开始读 | |
“w” | 以只写的创建新文件,如果该文件存在,则将文件里的内容覆盖(先清空再写)。 | 从头开始写 | |
“a” | 以只写的方式打开文件,将要写的内容追加到该文件原有的数据后面,如果该文件不存在,则创建该文件。 | 从末尾继续写 | |
“r+” | 以可读可写的方式打开文件,如果文件不存在则会报错。在写数据时会将原数据覆盖*****(先清空再写)。 | 从头开始读或写,如果打开文件后有多个读写操作接续上一次的读写位置。 | 注意:以这种方式打开文件,读文件的不会清空文件。 |
“w+” | 以可读可写的方式打开文件,如果文件不存在,则创建该文件,如果文件存在,写入数据时会将原内容覆盖*****(先清空再读,先清空再写)。 | 从头开始读或写,如果打开文件后有多个读写操作,则接续上一次的读写位置。 | 注意:以这种方式打开文件,读文件会先清空文件在执行度读操作,读取的数据量为0。 |
“a+” | 以可读可写的方式打开文件,如果文件不存在,则创建该文件,如果文件存在,写入数据时会追加在原数据后面。 | 从头开始读或从结尾接续写,如果打开文件后有多个读写操作,则接续上一次的读写位置。 |
注意:在读取字符数据的时候,无论数据有没有读完当读到 ‘\0’ 时,读结束。
二进制文件(Binary) | |||
---|---|---|---|
模式 | 功能描述 | 文件读写位置 | 备注 |
“rb” | 打开只读文件,文件必须存在,如果不存在则会报错。 | 从头开始读 | |
“wb” | 以只写的创建新文件,如果该文件存在,则将文件里的内容覆盖(先清空再写)。 | 从头开始写 | |
“ab” | 以只写的方式打开文件,将要写的内容追加到该文件原有的数据后面,如果该文件不存在,则创建该文件。 | 从末尾继续写 | |
“rb+” | 以可读可写的方式打开文件,如果文件不存在则会报错。在写数据时会将原数据覆盖*****(先清空再写)。 | 从头开始读或写,如果打开文件后有多个读写操作接续上一次的读写位置。 | *注意:以这种方式打开文件,读文件的不会清空文件。 |
“wb+” | 以可读可写的方式打开文件,如果文件不存在,则创建该文件,如果文件存在,写入数据时会将原内容覆盖*****(先清空再读,先清空再写)。 | 从头开始读或写,如果打开文件后有多个读写操作,则接续上一次的读写位置。 | *注意:以这种方式打开文件,读文件会先清空文件在执行度读操作,读取的数据量为0。 |
“ab+” | 以可读可写的方式打开文件,如果文件不存在,则创建该文件,如果文件存在,写入数据时会追加在原数据后面。 | 从头开始读或写,如果打开文件后有多个读写操作,则接续上一次的读写位置。 |
注意:在读取字符数据的时候,无论数据有没有读完当读到 ‘\0’ 时,读结束。
字符文件和二进制文件在我们自己使用的时候感觉不到区别,两者的用法相同。她俩的区别就是存储区别,例如:一个int 数字 147483647,如果按照字符存储,需要占用9个字节,如果按二进制存储就是int 本身的4个字节。 其实我感觉区别不大,因为我用文本文件的打开方式打开文件,存入int类型的数据它也是4个字节,也就是说你存什么类型的数据,它就占有那个类型的字节数。
二、fclose();文件关闭函数
-
函数声明: int fclose(FILE * stream);
-
函数功能: 关闭stream指向的文件,并将缓冲区内容写入文件
-
参数: 要关闭的文件的文件指针;
-
返回值: 关闭成功返回 0 ,关闭失败返回EOF (-1)
三、fwrite(); 文件写函数
-
函数声明: size_t fwrite(const void *restrict __ptr, size_t __size, size_t __n, FILE *restrict __s);
-
函数功能: 将__ptr指向的地址空间的的数据 ,以每次__size 个字节,写入__n 个 到文件指针 __s 指向的文件里
-
参数: 参数1: 指向要读取的数据的地址空间的指针; 参数2: 用户自定的元素的字节大小; 参数3: 一次写入几个元素; 参数4: 文件指针;
-
返回值:写入文件的字节数(size_t 就是long int)
四、fread(); 文件读函数
函数声明: size_t fread(void *restrict __ptr, size_t __size, size_t __n, FILE *restrict __stream)
函数功能: 从__stream指向的文件里读取__n个 __size字节大小的元素到__ptr指向的地址空间里;
参数: 参数1: 从文件中读取的内容要存放的地址空间,是一个指针; 参数2: 用户自定的元素的字节大小; 参数3: 一次读取几个元素; 参数4: 文件指针
返回值:写入文件的字节数(size_t 就是long int)
;
五、fseek();文件读写位置偏移函数
函数声明: int fseek(FILE *__stream, long __offest int __whence)
函数功能: 从当前读写位置偏移offest 字节,其中offest 可以为负数,负数就是向前偏移,0 就是不偏移,正数就是向后偏移。
参数: 参数1: 当前文件的文件指针 参数2:偏移量(可以为负数) 参数2: 偏移方式(三种方式:SEEK_SET、SEEK_CUR、SEEK_END)
偏移方式 | 功能描述 |
---|---|
SEEK_SET | 距文件开头偏移offest个字节 |
SEEK_CUR | 从当前偏移offest个字节 |
SEEK_END | 距文件末尾偏移offest个字节 |
返回值: 函数调用成功时则返回 0,若有错误则返回-1
六、rewind(); 文件读写位置重置函数
函数声明: void rewind(FILE *__stream);
函数功能: 将文件的读写位置移至文件开头
参数: 当文件的文件指针
返回值: 无
七、perror(); 错误提示函数
函数声明: void perror(const char *s);
函数功能: 将上一个函数发生错误的原因输出,先输出字符串s,然后再在字符串s后输出错误原因,字符串s和上一个发生错误的函数,没有一点关系你把它设置成 “张三” 都行。
例1:
例2:
参数: 用户自定的字符串(char*)
返回值: 无
八、exit(); 终结当前进程函数
函数声明: void exit(int status);
函数功能: 正常结束当前进程的执行,而进程所有的缓冲区里的数据会自动写回并关闭未关闭的文件。
参数: 参数:0或非0,当值为0时,表示程序正常退出; 非0值时,表示程序异常退出。
返回值: 无
PS: 我们也可以使用return结束当前函数或程序 return 0(正常结束)、return -1(异常结束) ,会将缓冲区内容写入文件然后结束程序
对以上八个函数进行运用,例程如下:
#include<stdio.h>
#include<string.h>
int main(void)
{
FILE *fp = NULL;
char str[50] = {0};
char buf[50] = {0};
/*
fopen
函数声明: FILE *fopen(const char *__restrict__ __filename, const char *__restrict__ __modes);
函数功能: 根据 __modes设定的读写方式,创建\打开文件
参数: 参数1: 文件路径名(可以是char*变量); 参数2: 文件读写方式;
返回值: 打开成功返回文件指针 打开失败返回NULL
*/
if((fp = fopen("file1.txt","w+")) == NULL) // 以读写的方式打开或创建文件file1.txt。
{
perror("fopen"); // 打开失败给出错误信息
if(fclose(fp) == EOF) //关闭文件
{
perror("fclose"); //文件关闭失败给出错误信息
exit(0); // 关闭文件失败,退出进程
}
}
printf("请输入:\n");
gets(str); // 从命令行界面获取字符串
/*
fwrite
函数声明: size_t fwrite(const void *__restrict__ __ptr, size_t __size, size_t __n, FILE *__restrict__ __s);
函数功能: 将__ptr指向的地址空间的的数据 ,以每次__size 个字节,写入__n 个 到文件指针 __s 指向的文件里
参数: 参数1: 指向要读取的数据的地址空间的指针; 参数2: 用户自定的元素的字节大小; 参数3: 一次写入几个元素; 参数4: 文件指针;
返回值:写入文件的字节数(size_t 就是long int)
*/
int num = fwrite(str,strlen(str),1,fp);
printf("Write %d byte\n",num);
/*
rewind
函数声明: void rewind(FILE *__stream);
函数功能: 用来把文件流的读写位置移至文件开头。
参数: 参数: 文件指针;
返回值: 无
*/
rewind(fp); // 将文件读写位置置于文件开头
// fseek(fp,0,SEEK_SET); // 距文件开头偏移0个字节,即文件开头
/*
fread
函数声明: size_t fread(void *__restrict__ __ptr, size_t __size, size_t __n, FILE *__restrict__ __stream)
函数功能:
参数: 参数1: 从文件中读取的内容要存放的地址空间,是一个指针; 参数2: 用户自定的元素的字节大小; 参数3: 一次读取几个元素; 参数4: 文件指针
返回值:写入文件的字节数(size_t 就是long int)
*/
int n = fread(buf,strlen(str),1,fp);
printf("Read %d byte\n",n);
printf("读出的结果:%s\n",buf);
fclose(fp);
}
九、fprintf(); 格式化输出内容到文件
函数声明: int fprintf(FILE * stream, const char * format,…);
函数功能: 根据参数format字符串来转换并格式化数据,然后将结果输出到参数stream指定的文件中,直到出现字符串结束符( ‘\0’ )为止. 其实就是把不同类型的数据,转换为字符串输出到指定字符串。
参数: stream:文件指针;format : 字符串的格式 ; 其他参数:和字符串format里的格式符相对应类型的变量
返回值: 成功把内容输出到文件则返回实际输出的字符数,失败则返回-1.
例:
十、fscanf(); 从文件中格式化读取内容
函数声明: int fscanf(FILE * stream ,const char *format,…);
函数功能: 从stream指向的文件流中读取字符串,再根据format字符串格式来转换和格式化数据,将对应的数据写入到与格式符对应类型的变量。
参数: stream:文件流指针; format:字符串读取的格式; 其他参数:将字符串里相应的字符转换为格式符对应的变量类型,并赋值给对应的变量
返回值: 成功则返回参数数目,失败则返回-1
注意:读取的字符串和要转换的字符串 字符的位置、数量、格式符的位置要一模一样,例如从文件里读取 “ PI = 3.14159 ” , fscanf里的字符串必须是“ PI = %lf ”,这样才能把3.14159 准确无误的转换成 double类型的数据。
十一、printf();
函数声明: int printf(const char * format,…);
函数功能: 根据参数format字符串来转换并格式化数据,并将结果输出到标准输出设备,遇到 ‘ \0 ’ 停止
参数: %(flags) (width) (.digit) type
括号内是可选的参数,其中%和type是固定搭配
flags:
’ - ’ : 当flag是这个’ - '时(不包括单引号),表示该type对应的变量输出时左对齐,不加该符号默认右对齐
’ + ’ : 我们知道当我们打印一个负数时,会自动在前面加一个符号,正数默认不加,加上这个符号正数也默认加正号
’ # ’ :此符号会根据其后转换字符的不同而有不同含义。当在类型为o 之前(如%#o),则会在打印八进制数值前多印一个 o。而在类型为 x 之前(%#x)则会在打印十六进制数前多印’0x’,在型态为 e、E、f、g 或 G 之前则会强迫数值打印小数点。在类型为 g 或 G 之前时则同时保留小数点及小数位数末尾的零。
’ 0 ’ : 字符零当指定输出宽度时,想左空位补零
width: 指定type对应变量输出字符时占有的宽度
digit:
1. 如果是数字的话 : 表示保留几个数据位,对整数不起作用,对浮点数就是保留digit位小数,对于字符串就是输出digit个字符。如下图所示:
2.在%g 格式下代表保留digit位有效数字(四舍五入,小数点前的数字位也算上)
3.如果digit 不是数字,而是 * 则可以指定一个可变数字,控制输出的数据位,例如:可以通过变量控制每次打印的字符数,来打印直角三角形,如下图所示:
’ * ’ 也可以这样使用,如下所示:
printf("weight = %*.*f\n",width,precision,weight);
type的可选参数如下表所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XKNRRF65-1639191213037)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20211202154322970.png)]
返回值: int类型 ,返回输出的字符数
十二、scanf();
函数声明: int scanf(const char * format,…);
函数功能: 根据 fromat字符串来转换并格式化数据
参数: % ( * ) ( size ) ( l ) ( h ) type , 括号内为可选参数,其中%和type这两个符号是固定搭配
- ***** :代表该对应的参数数据忽略不保存 , 示例如下如所示:
- size :表示允许输入的数据长度
- l : 输入的数据数值以 long int 或 double 型保存
- h :输入的数据数值以 short int 型保存
- type : type的可选形式及功能 如下表所示:
图1 %i 演示图
返回值: 成功则返回参数数目,失败则返回-1
十三、sprintf();
函数声明: int sprintf( char *str,const char * format,…);
函数功能: 将格式化字符串写入到 str 指向的地址空间里
参数: str: 字符串指针,指向一个地址空间,用于存储格式化的字符串,format: 格式化字符串
返回值: 返回写入str中的字符个数
十四、sscanf();
函数声明: int sscanf (const char *str,const char * format,…);
函数功能: 将str字符串按照 format的格式进行格式化,将与格式符对应的字符转换为相应类型变量,并赋值给对应类型的变量
参数: str: 要转换的字符串, format:要转换的字符串格式
返回值: 成功则返回参数数目,失败则返回-1
十五、fflush、
函数声明: int fflush(FILE* stream);
函数功能: 刷新缓冲区,将缓冲区里的数据写入文件
参数: stream:文件指针
返回值: 成功返回 0,失败返回 EOF
十六、fgetc()
函数声明: int fgetc(FILE * stream);
函数功能: 从文件指针stream 所指的文件中读取一个字符。若读到文件尾而无数据时便返回 EOF。
参数: stream:文件流指针
返回值: 返回读取到的字符,若返回 EOF 则表示到了文件尾
这里存疑:
十七、fputc()
函数声明: int fputc(int c,FILE * stream);
函数功能: fputc 会将参数 c 转为 unsigned char 后写入参数 stream 指定的文件中
参数: c:要写入的字符 , strean : 文件流指针
返回值: 写入成功返回写入的字符,即参数 c。若写入失败返回 EOF
十八、fgets()
函数声明: char * fgets(char * s,int size,FILE * stream);
函数功能: fgets()用来从参数 stream 所指的文件内读入字符并存到参数 s 所指的内存空间,直到出现换行字符、读到文件尾或是已读了 size-1个字符为止, 最后会加上 NULL 作为字符串结束
参数: s: 要存放字符串的地址 , size: 要读取size个字符串,其中最后一个字符是 ‘\0’ ,也就是实际读取的字符数为size-1个 ,stream:文件流指针
返回值: 若读取成功则返回 s 指针,返回 NULL 则表示有错误发生。
十九、fputs()
函数声明: int fputs(const char * s,FILE * stream);
函数功能: fputs() 用来将参数 s 所指的字符串写入到参数 stream 所指的文件内 ,遇到 '\0’停止输出 ,遇到换行不影响
参数: s : 字符串存取的地址 , stream: 文件流指针
返回值: 若写入成功则返回写出的字符个数,写入失败返回 EOF
二十、getc()
函数声明: int getc(FILE * stream);
函数功能: getc()用来从参数 stream 所指的文件中读取一个字符。若读到文件尾而无数据时便返回 EOF。虽然 getc()与 fgetc()作用相同,
但 getc()为宏定义,非真正的函数调用。
参数: stream:文件流指针
返回值: 成功则返回输出成功的字符的ASSIC码值,即参数 c。失败则返回 EOF
二十一、putc()
函数声明: int putc(int c,FILE * stream);
函数功能: putc()会将参数 c 转为 unsigned char 后写入参数 stream 指定的文件中。虽然 putc()与 fputc()作用相同,但 putc()为宏定义,非真正 的函数调用
参数: c : 字符的ASSIC码值, stream : 文件流指针
返回值: 成功则返回输出成功的字符的ASSIC码值,即参数 c。失败则返回 EOF
二十一、gets()
函数声明: char * gets(char *s);
函数功能: gets()用来从标准设备读入字符并存到参数 s 所指的内存空间,直到出现换行字符或读到文件尾为止,最后加上 NULL 作为字符串结束。
参数: s : 字符串指针
返回值: 成功则返回 s 指针,返回 NULL 则表示有错误发生
注意:gets()无法知道字符串 s 的大小,必须遇到换行字符或文件尾才会结束输入,因此容易造成缓冲区溢出的安全性问题。建议使用fgets()取代。
二十二、puts()
函数声明: int puts(const char *s);
函数功能: 将字符串 s 输出,遇到 ‘\0’ 文件尾结束
参数: s : 字符串指针
返回值: 成功则返回写出的字符个数,写入失败返回 EOF
二十三、getchar()
函数声明: int getchar(void);
函数功能: getchar() 用来从标准输入设备(键盘)中读取一个字符。然后将该字符从unsigned char 转换成 int 后返回。
参数: 无
返回值: 成功则字符的 ASSIC 值,返回 EOF 则表示有错误发生
二十四、putchar()
函数声明: int putchar (int c);
函数功能: putchar() 用来将ASSIC码值为 c 字符写到标准输出设备
参数: c : 字符的ASSIC码值
返回值: 成功则返回输出成功的字符的ASSIC码值,即参数 c。失败则返回 EOF
putchar (int c); 是 putc(c,stdout)宏定义
fgetc, fputc, getc, putc, getchar, putchar
fgets, fputs, gets, puts
函数声明: int getchar(void);
函数功能: getchar() 用来从标准输入设备(键盘)中读取一个字符。然后将该字符从unsigned char 转换成 int 后返回。
参数: 无
返回值: 成功则字符的 ASSIC 值,返回 EOF 则表示有错误发生
二十四、putchar()
函数声明: int putchar (int c);
函数功能: putchar() 用来将ASSIC码值为 c 字符写到标准输出设备
参数: c : 字符的ASSIC码值
返回值: 成功则返回输出成功的字符的ASSIC码值,即参数 c。失败则返回 EOF
putchar (int c); 是 putc(c,stdout)宏定义
fgetc, fputc, getc, putc, getchar, putchar
fgets, fputs, gets, puts