一、文件操作方法
linux中有两种方法可以操作文件:系统调用和c库函数。
1. 什么是系统调用?
由操作系统实现并提供给外部应用程序的编程接口(API),是应用程序同系统之间数据交互的桥梁。
C标准函数和系统函数调用关系,如图:
2. c库函数
待写。
二、文件IO(系统调用API)
库函数头文件统一使用头文件unistd.h 。
1. open创建
头文件:
#include <fcntl.h>
函数原型:
int open(const char *pathname, int flags);
参数说明:
flag参数 | 说明 |
---|
O_RDONLY | 只读方式打开 | O_WRONLY | 只写方式打开 | O_RDWR | 可读可写 | O_CREAT | 文件不存在则创建(文件权限由mode参数指定) | O_APPEND | 追加方式写入 | O_EXCL | 判断文件是否存在 | O_TRUNC | 截断文件大小为0/清空文件 | O_NONBLOCK | |
mode权限参数说明:
- 该参数使用八进制指定;
- 该参数受umask(默认0002)影响:最终权限 = mode &~ umask,其实就是把我们所指定权限中other用户的写权限给去除。
返回值说明:
- 成功返回fd号
- 失败返回-1,错误原因errno给出
2. close关闭
头文件:
#include <unistd.h>
函数原型:
int close(int fd);
参数说明:
3. write写入
头文件:
#include <unistd.h>
函数原型:
ssize_t write(int fd, const void *buf, size_t count);
参数说明:
- fd:文件描述符
- buf:待写数据指针
- count:待写数据大小
返回值:
- 成功:返回写入的字节数
- 失败:返回-1,error被设置
4. read读取
头文件:
#include <unistd.h>
函数原型:
ssize_t read(int fd, void *buf, size_t count);
参数说明:
- fd:文件描述符
- buf:缓冲区指针
- count:要读取的数据大小
返回值:
- 成功:返回读取的字节数
- 失败:返回-1,error被设置
说明:
在支持查找的文件上,读取操作从文件偏移量开始,并且文件偏移量会随着读取递增。如果文件偏移量在文件末尾或者超过文件末尾,则返回0。
5. lseek文件偏移
头文件:
#include <unistd.h>
函数原型:
off_t lseek(int fd, off_t offset, int whence);
参数说明:
- fd:文件描述符
- offset:偏移量
- count:要读取的数据大小
- SEEK_SET:The file offset is set to offset bytes.
- SEEK_CUR:The file offset is set to its current location plus offset bytes.
- SEEK_END:The file offset is set to the size of the file plus offset bytes.
返回值:
- 成功:返回当前所在偏移量
- 失败:返回-1,error被设置
三、测试程序
demo1——默认创建文件的权限
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd;
fd = open("hello.txt", O_RDWR | O_CREAT);
printf("fd is %d\n", fd);
close(fd);
return 0;
}
执行结果:
fd is 3
如果hello.txt不存在,则open会创建该文件,但我们并没有指定文件权限(mode),查看默认创建文件的权限:
---Srwx--T 1 ubuntu ubuntu 0 Sep 5 16:40 hello.txt
后续文件权限分析?
demo2——指定创建文件的权限
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd;
fd = open("hello.txt", O_RDWR | O_CREAT, 0644);
printf("fd is %d\n", fd);
close(fd);
return 0;
}
执行之后再次查看hello.txt的权限:
rw-r--r-- 1 ubuntu ubuntu 0 Sep 5 16:47 hello.txt
demo3——指定创建文件的权限受umask影响
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd;
fd = open("hello.txt", O_RDWR | O_CREAT, 0777);
printf("fd is %d\n", fd);
close(fd);
return 0;
}
创建出的hello.txt权限为:
-rwxrwxr-x 1 ubuntu ubuntu 0 Sep 5 17:03 hello.txt*
demo4-打开文件出错
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd;
fd = open("hello.txt", O_RDWR);
printf("fd is %d\n", fd);
printf("errno is %d(%s)\n", errno, strerror(errno));
close(fd);
return 0;
}
当hello.txt不存在时,日志为:
fd is -1
errno is 2(No such file or directory)
demo5——文件偏移量导致读取失败
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd;
int nbytes;
char write_buf[] = "helloworld!";
char read_buf[1024] = {0};
fd = open("hello.txt", O_RDWR | O_CREAT, 0664);
if (fd < 0) {
printf("open fail, fd is %d\n", fd);
printf("errno is %d(%s)\n", errno, strerror(errno));
return -1;
}
nbytes = write(fd, write_buf, sizeof(write_buf));
if (nbytes < 0) {
printf("write fail, errno is %d(%s)\r\n", errno, strerror(errno));
return -1;
}
printf("write %d bytes\r\n", nbytes);
nbytes = read(fd, read_buf, sizeof(read_buf));
if (nbytes < 0) {
printf("read fail, errno is %d(%s)\r\n", errno, strerror(errno));
return -1;
}
printf("read %d bytes:[%s]\r\n", nbytes, read_buf);
close(fd);
return 0;
}
write写入完成后,文件偏移量在文件末尾,直接读取导致返回0:
write 12 bytes
read 0 bytes:[]
这个时候在read之前,使用lseek函数将文件偏移量恢复到文件开始处即可:
lseek(fd, 0, SEEK_SET);
|