文件的打开及创建
打开文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
pathname :要打开的文件名
flags:O_RDONLY 只读打开 O_WRONLY 只写打开 O_RDWR 可读可写打开
同时可以附加以下常数:
- O_CREAT 若文件不存在则创建它。同时必须在mode参数附加文件存取许可权限。
- O_EXCL 如果同时指定了O_CREAT,而文件已经存在,则出错。
- O_APPEND 每次写时都加到文件的尾端。
- O_TRUNC 打开文件时,如果这个文件中本来是有内容的,而且为只读或者只写成功打开,则将其长度揭短为0
mode:一定是在flag中使用了O_CREAT标志,mode主要记录待创建文件的访问权限
返回值: 返回的是一个文件描述符,一个小的非负整数
权限简介:
- Linux系统上对文件的权限有着严格的控制,如果想对某个文件执行某种操作,必须具有对应的权限方可执行成功。
- Linux下文件的权限类型一般包括读,写,执行。对应字母为 r、w、x。
- Linux下权限的粒度有 拥有者 、群组 、其它组 三种。每个文件都可以针对三个粒度,设置不同的rwx(读写执行)权限。通常情况下,一个文件只能归属于一个用户和组, 如果其它的用户想有这个文件的权限,则可以将该用户加入具备权限的群组,一个用户可以同时归属于多个组;r 4;w 2;x 1;模式的参数必须按这样写才能起到对三个粒度的权限控制
参数为00400为仅可读
参数为00200为仅可写
参数为00100为可执行
可读可写可执行为00700
demo1
可读可写方式打开文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd;
fd = open("./file",O_RDWR); //打开文件
printf("fd = %d\n",fd); //输出文件描述符
return 0;
}
demo2
打开文件,如果文件不存在,创建该文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd;
fd = open("./file",O_RDWR); //打开文件
if(fd==-1){
printf("open file failed\n");
fd = open("./file",O_RDWR|O_CREAT,0600); //创建文件
if(fd>0){
printf("Create file success\n");
}
}
return 0;
}
创建文件
一般不用该函数,一般为open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int creat(const char *pathname, mode_t mode);
pathname :要打开的文件名
mode:一定是在flag中使用了O_CREAT标志,mode主要记录待创建文件的访问权限
- S_IRUSR 4 可读
- S_IWUSR 2 可写
- S_IXUSR 1 可执行
- S_IRWXU 7 可读可写可执行
这里mode的参数也可以使用上面open中的mode参数
demo
创建一个文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
//创建文件
int main()
{
int fd;
fd = creat("./file2temp",S_IRWXU); //创建一个文件,权限为可读可写可执行
printf("%d\n",fd);
return 0;
}
一些文件的打开及创建的测试demo
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
//判断文件是否存在,如果不存在则会创建文件
int main()
{
int fd;
fd = open("./file",O_RDWR|O_CREAT|O_EXCL,0600);
if(fd==-1){
printf("file exist\n");
}
return 0;
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
//每次写为在文件末尾出增加
int main()
{
int fd;
char *buf = "写测试。。";
fd = open("./file",O_RDWR|O_APPEND);
write(fd,buf,strlen(buf));
return 0;
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
//清除原来文本内容重新写
int main()
{
int fd;
char *buf = "写测试。。";
fd = open("./file",O_RDWR|O_TRUNC);
write(fd,buf,strlen(buf));
return 0;
}
文件写入操作
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
fd:文件描述符
buf:需要写的内容
count:待写入的字节个数
返回:读取到的个数,一般0为失败
demo
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
int main()
{
int fd;
char *buf = "写测试。。";
fd = open("./file",O_RDWR);
if(fd==-1){
printf("open file failed\n");
fd = open("./file",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("Create file success\n");
}
}
printf("open success : fd = %d\n",fd);
int n_wrte = write(fd,buf,strlen(buf));
if(n_wrte>0){
printf("write %d byte success",n_wrte);
}
else
perror("write");
close(fd);
return 0;
}
文件读取操作
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
fd:文件描述符
buf:待读取缓冲区
count:读取个数
返回:读取到的个数,一般0为失败
demo
从文件中读取
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf = "写测试。。";
fd = open("./file",O_RDWR);
if(fd==-1){
printf("open file failed\n");
fd = open("./file",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("Create file success\n");
}
}
printf("open success : fd = %d\n",fd);
int n_write = write(fd,buf,strlen(buf));
if(n_write!=-1){
printf("write %d byte to file\n",n_write);
}
close(fd);
//这里必须重新打开或者重置光标
fd = open("./file",O_RDWR);
char *readbuf;
readbuf = (char *)malloc(sizeof(char)*n_write+1);
int n_read = read(fd,readbuf,n_write);
printf("read %d,context:%s\n",n_read,readbuf);
close(fd);
return 0;
}
文件光标移动操作
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
fd:文件描述符
offset:偏移量
whence:从何处写
- SEEK_SET:要偏移的个数等于offset
- SEEK_CUR:当前位置加上offset
- SEEK_END:文件大小加上偏移字节
返回:成功偏移的字节数
demo
测试文件大小
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
//计算文件大小
int main()
{
int fd;
fd = open("./file",O_RDWR);
int filesize = lseek(fd,0,SEEK_END);
printf("fize size is %d\n",filesize);
close(fd);
return 0;
}
文件操作原理简述
虚拟空间地址/PCB进程控制块/文件描述符表
对于每一个进程,系统都会为其分配一个0-4G的虚拟空间地址,0-3G为用户空间,用户可操作部分。3~4G为内核,其中PCB控制块也存在内核中(补充:每一个进程都有一个PCB)PCB结构体包括文件标识符表以及其他很多信息。
文件描述符表,结构体 PCB 的成员变量 file_struct *file 指向文件描述符表。从应用程序使用角度,该指针可理解记忆成一个字符指针数组,下标 0/1/2/3/4…找到文件结构体。本质是一个键值对 0、1、2…都分别对应具体地址。但键值对使用的特性是自动映射,我们只操作键不直接使用值。新打开文件返回文件描述符表中未使用的最小文件描述符。
与标准C库的区别
补充-linux man 1 2 3的作用
1、Standard commands (标准命令)
2、System calls (系统调用)
3、Library functions (库函数)
4、Special devices (设备说明)
5、File formats (文件格式)
6、Games and toys (游戏和娱乐)
7、Miscellaneous (杂项)
8、Administrative Commands (管理员命令)
9 其他(Linux特定的), 用来存放内核例行程序的文档。
例如
man 1 ls
man 2 open
man 3 printf
标准c库实现linux内核态的读写操作
打开文件函数
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
pathname:文件路径
mode:模式
- r 只读方式打开一个文本文件
- r+ 可读可写方式打开一个文本文件
- w 只写方式打开一个文本文件 (w没有就创建)
- w+ 可读可写方式创建一个文本文件
- wb 只写方式打开一个二进制文件
- a 追加方式打开一个文本文件
- ab 追加方式打开一个二进制文件
- rb 只读方式打开一个二进制文件
- rb+ 可读可写方式打开一个二进制文件
- wb+ 可读可写方式生成一个二进制文件
- a+ 可读可写追加方式打开一个文本文件
- b+ 可读可写方式追加一个二进制文件
返回值:返回一个文件指针
写文件函数
#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
ptr:写入内容的指针
size:一次写多少个字符
nmemb:字符个数
stream:which file
返回值:返回写入的个数
读文件函数
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
ptr:读入内容的指针
size:一次读多少个字符
nmemb:字符个数
stream:which file
返回值:返回读入的个数
光标移动函数
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
stream:which file
offset:偏移量
whence:从何处写
- SEEK_SET:要偏移的个数等于offset
- SEEK_CUR:当前位置加上offset
- SEEK_END:文件大小加上偏移字节
返回值:返回偏移的个数
读写测试
#include <stdio.h>
#include <string.h>
// FILE *fopen(const char *pathname, const char *mode);
int main()
{
FILE *fp;
char *str = "write read testing";
char readbuf[128]={0};
fp = fopen("./file3","w+");
fwrite(str,sizeof(char),strlen(str),fp);
fseek(fp,0,SEEK_SET);
int n_read = fread(readbuf,sizeof(char),strlen(str),fp);
printf("read %d byte,context:%s\n",n_read,readbuf);
fclose(fp);
}
写入一个字符
#include <stdio.h>
int fputc(int c, FILE *stream);
c:待写入的字符
stream:which file
返回值:返回写入成功字符
读出一个字符
#include <stdio.h>
int fgetc(FILE *stream);
FILE :which file
返回值:返回读出成功字符
检查光标是否到达文件末尾
#include <stdio.h>
int feof(FILE *stream);
FILE :which file
返回值:是为大于0的数,否为0
demo
读取字符串
#include <stdio.h>
#include <string.h>
// FILE *fopen(const char *pathname, const char *mode);
int main()
{
FILE *fp;
char readbuf[128]={0};
char dat = 0;
fp = fopen("./file3","a+");
fseek(fp,0,SEEK_SET);
while(!feof(fp))
{
dat = fgetc(fp);
printf("%c",dat);
}
printf("\nread ok\n");
fclose(fp);
}