提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、C语言的文件接口操作
"r"模式
- 打开文件只读操作,即只能读取文件操作。
- 若要打开的文件不存在,即打开失败。
- 打开成功后,文件的指针位于文件开头。
- 打开文件后,不会清空文件内容。
- 可以从文件的任意位置读取文件内容。
"w"模式
- 打开文件只写操作,即只能对文件进行写入内容。
- 若要打开的文件不存在,即自动在该进程的当前路径进行创建。
- 打开成功后,文件的指针位于文件开头。
- 打开文件后,会清空文件内容。
- 可以从文件的任意位置对文件写入内容,只要以w模式打开文件后,都会清空文件原本的内容。
"a"模式
- 打开文件追加操作,即只能对文件进行写入内容。
- 若要打开的文件不存在,即自动在该进程的当前路径进行创建。
- 打开成功后,文件的指针位于文件结尾。
- 打开文件后,不会清空文件内容。
- 只能在文件的末尾,进行写入内容。
"r+"模式
- 打开文件读写操作,可以对文件进行读写操作。
- 若要打开的文件不存在,即打开失败。
- 打开成功后,文件的指针位于文件开头。
- 打开文件后,不会清空文件内容。
- 可以从文件的任意位置读写文件,写操作时会覆盖原有的内容。
"w+"模式
- 打开文件读写操作,可以对文件进行读写操作。
- 若要打开的文件不存在,即自动在该进程的当前路径进行创建。
- 打开成功后,文件的指针位于文件开头。
- 打开文件后,会清空文件内容。
- 可以从文件的任意位置读写文件,写操作时会覆盖原有的内容。
"a+"模式
- 打开文件读写操作,可以对文件进行读写操作。
- 若要打开的文件不存在,即自动在该进程的当前路径进行创建。
- 打开成功后,文件的指针位于文件结尾。
- 打开文件后,不会清空文件内容。
- 读操作时可以在文件的任意位置,如果要进行写操作时只能在文件末尾。
二进制模式
- rb。
- wb。
- ab。
- rb+ || r+b。
- wb+ || w+b。
- ab+ || a+b。
其中,二进制模式与文本模式操作相似,只不过是以二进制流的形式读写而已。
示例:
#include <stdio.h>
#define FILE_NAME "log.txt"
int main()
{
//使用c语言提供的fopen以w模式打开文件
FILE* fp = fopen(FILE_NAME,"w");
//如果失败 fp会是NULL
if(NULL == fp)
{
perror("fopen");
return 1;
}
int cnt = 0;
while(cnt != 6)
{
//使用fprintf对文件进行写入内容
fprintf(fp,"%s:%d\n","hello world!",cnt++);
}
//关闭文件
fclose(fp);
return 0;
}
执行结果
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define FILE_NAME "log.txt"
int main()
{
//使用r模式,对文件进行读操作
FILE* fp = fopen(FILE_NAME,"r");
//如果失败 fp会是NULL
if(NULL == fp)
{
perror("fopen");
return 1;
}
//把读到的内容,存到buffer数组里面
char buffer[64];
//使用fgets对文件进行读
while(fgets(buffer,sizeof (buffer)-1,fp) != NULL)
{
//由于puts是对行进行输出的,会默认增加一个\n,我们的文件内容也有一个\n,所以需要把多余的\n置为\0
buffer[strlen(buffer)-1] = '\0';
//输出读到的内容
puts(buffer);
}
fclose(fp);
return 0;
}
执行结果
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define FILE_NAME "log.txt"
int main()
{
//使用a模式进行追加
FILE* fp = fopen(FILE_NAME,"a");
if(NULL == fp)
{
perror("fopen");
return 1;
}
int cnt = 0;
while(cnt != 6)
{
//使用fprintf进行写入
fprintf(fp,"%s:%d\n","hello world!",cnt++);
}
fclose(fp);
return 0;
}
执行结果,每执行一次,追加五行内容
默认C语言文件创建权限
我们用c语言创建的文件,默认的权限是664,为什么是664呢,因为默认的文件权限是666 & ~0002(umask值),即666与上(0002取反),所以默认的文件是664.
二、系统提供的文件接口
标记位
在使用系统提供的文件接口时,我们先认识一下,标记位。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#define ONE (1<<0)
#define TWO (1<<1)
#define THREE (1<<2)
#define FOUR (1<<3)
void show(int flags)
{
if(flags & ONE) printf("one\n");
if(flags & TWO) printf("two\n");
if(flags & THREE) printf("three\n");
if(flags & FOUR) printf("four\n");
}
int main()
{
show(ONE);
printf("-------------------\n");
show(ONE | TWO);
printf("-------------------\n");
show(ONE | TWO | THREE);
printf("-------------------\n");
show(ONE | TWO | THREE | FOUR);
printf("-------------------\n");
return 0;
}
执行结果
一个整数有32个比特位,我们可以利用这32个比特位,传递很多的参数,例如我们上面做的实验,我们可以同时传递ONE TWO THREE FOUR,只要用上或运算,即一个参数,可以得到,我们要传递的四个信息,系统提供的文件接口里面,也有一个标记位,就是我们接下来使用的系统接口open。
open
open是系统提供的文件接口,C语言等很多语言的文件接口,都是封装了系统提供的文件接口,熟悉了底层的接口,上层的接口基本都会明白,可以给我们省很多学习成本。
//头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//open有两个,一个是针对已经有的文件,一个是针对没有的文件
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
接口介绍:
pathname: 要打开或创建的目标文件名
flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags标记位。
参数:
(可以认为是宏,实际可以理解为跟上方的标记位示例ONE TWO一样的)
O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND: 追加写
返回值:
成功:新打开的文件描述符
失败:-1
mode_t理解: mode_t 只有当在flags参数中使用 O_CREAT 时 才 有效 , 否则被忽略,mode_t是文件的权限大小.
open 函数具体使用哪个,和具体应用场景相关,如目标文件不存在,需要open创建,则第三个参数表示创建文件
的默认权限,否则,使用两个参数的open
示例:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#define FILE_NAME "txt.txt"
int main()
{
int fd = open(FILE_NAME,O_RDONLY | O_CREAT,0666);
//如果失败,fd open会返回-1,成功会返回对应的描述符
if(-1 == fd)
{
perror("open");
return 1;
}
close(fd);
return 0;
}
执行结果
write
往文件中写入内容
#include <unistd.h>//头文件
//函数原型
ssize_t write(int fd, const void *buf, size_t count);
fd是我们用open成功打开后返回的描述符,buf是缓冲区,count是要写入的个数,write写入成功后,会返回对应写入了多少个字符,出错返回-1.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#define FILE_NAME "txt.txt"
int main()
{
//我们要写操作,所以要用O_WRONLY标记位
int fd = open(FILE_NAME,O_WRONLY);
if(-1 == fd)
{
perror("open");
return 1;
}
int cnt = 0;
char buffer[1024];
while(cnt != 6)
{
sprintf(buffer,"%s%d\n","hello world!",cnt++);
write(fd,buffer,strlen(buffer));
}
close(fd);
return 0;
}
执行结果:
read
从文件中读取内容
//头文件
#include <unistd.h>
//函数原型
ssize_t read(int fd, void *buf, size_t count);
fd是open打开文件后返回的文件描述符,buf是我们读到的数据存放的位置,count是代表要读取多少个字符,读取成功后会返回读取到的字符个数,出错返回-1.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#define FILE_NAME "txt.txt"
int main()
{
//我们要读操作,所以用O_RDONLY
int fd = open(FILE_NAME,O_RDONLY);
if(-1 == fd)
{
perror("open");
return 1;
}
char buffer[1024];
const char* msg = "hello world!";
while(1)
{
ssize_t s = read(fd,buffer,strlen(msg));
if(s > 0)
{
printf("%s",buffer);
}
else
{
break;
}
}
close(fd);
return 0;
}
执行结果