文章目录
1. 文件打开/创建
#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);
int creat(const char *pathname, mode_t mode);
参数:
pathname: 要打开的文件路径名
flags: 文件打开的方式 :
- O_RDONLY 只读打开
- O_WRONLY 只写打开
- O_RDWR 可读可写打开
以上这三个常数中应当只指定一 个。下列常数是可选择的:
- O_CREAT 若文件不存在则创建它。使用此选项时,需要同时说明第三个参数mode,用其说明该新文件的存取许可权限。
- O_EXCL 如果同时指定了O_CREAT,而文件已经存在,则出错。
- O_APPEND 每次写时都加到文件的尾端。(追加文件)
- O_TRUNC 属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截短为0。(覆盖文件)
mode: 参数使用的前提, 参数flags指定了 O_CREAT。使用8进制数,用来描述文件的访问权限。 例:rwx 0664
返回值:
- 成功: 打开文件所得到对应的 文件描述符(整数)
- 失败: -1, 并把错误代码设给errno
#include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5
6 int main() {
7 int fd;
8 fd = open("./file1", O_RDWR);
9
10 if (fd == -1) {
11 printf("open file1 failed\n");
12 fd = open("./file1", O_RDWR|O_CREAT, 0600);
13 if (fd > 0) {
14 printf("create file1\n");
15 }
16 }
17 return 0;
18 }
输出:
open file1 failed
create file1
2. 错误处理函数
char *strerror(int errnum); // 将错误码转换为相应的错误消息字符串
printf("xxx error: %s\n", strerror(errno));
/*
将上一个函数发生错误的原因输出到标准设备 stderr
参数 s 所指的字符串会先打印出,后面再加上错误原因字符串
此错误原因依照全局变量errno的值来决定要输出的字符串
*/
void perror(const char *s);
perror("open error");
3. close 函数
#include <unistd.h>
int close(int fd);
参数:
- fd: 文件描述符
返回值:
- 成功: 0
- 失败: -1, 并设置errno
4. 写入文件(write)
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
参数:
- fd: 文件描述符
- buf:待写出数据的缓冲区
- count:写入字节数(数据大小)
返回值:
- 成功: 写入的字节数
- 失败: -1, 并设置errno
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <string.h>
6
7 int main() {
8 int fd;
9 char *buf = "hello hello";
10 fd = open("./file1", O_RDWR);
11
12 if (fd == -1) {
13 printf("open file1 failed\n");
14 fd = open("./file1", O_RDWR|O_CREAT, 0600);
15 if (fd > 0) {
16 printf("create file1\n");
17 }
18 }
19 int count = write(fd, buf, strlen(buf));
20 printf("write byte count: %d\n", count);
21 int isClose = close(fd);
22 if (isClose == 0) {
23 printf("close success\n");
24 }
25 return 0;
26 }
执行结果:
open file1 failed
create file1
write byte count: 11
close success
5. 读取文件(read)
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
参数:
- fd:文件描述符
- buf:存数据的缓冲区
- count:缓冲区大小
返回值:
- 0:读到文件末尾。
- 成功; > 0 读到的字节数
- 失败: -1, 设置 errno
- 注:-1 并且 errno = EAGIN 或 EWOULDBLOCK, 说明不是read失败,而是read在以非阻塞方式读一个设备文件(网络文件),并且文件无数据。
1#include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 int main() {
9 int fd;
10 char *buf = "hello hello";
11 fd = open("./file1", O_RDWR);
12
13 if (fd == -1) {
14 printf("open file1 failed\n");
15 fd = open("./file1", O_RDWR|O_CREAT, 0600);
16 if (fd > 0) {
17 printf("create file1\n");
18 }
19 }
20 int count = write(fd, buf, strlen(buf));
21 printf("write byte count: %d\n", count);
22 int isClose = close(fd);
23 if (isClose == 0) {
24 printf("close success\n");
25 }
26
27 fd = open("./file", O_RDRW); // 重新打开文件,使文件光标到文件开头
28 char *buf1 = (char *) malloc(sizeof(char) * count +1);
29 int read_byte = read(fd, buf1, count);
30 printf("read count: %d, read context: %s\n", count, buf1);
31 close(fd);
32
33 return 0;
34 }
执行结果:
write byte count: 11
close success
read count: 11, read context: hello hello
6. 文件偏移(lseek)
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
参数:
- fd:文件描述符
- offset: 偏移量
- whence:起始偏移位置 SEEK_SET/SEEK_CUR/SEEK_END
返回值:
- 成功:较起始位置偏移量
- 失败:-1,设置 errno
应用场景:
- 文件的“读”、“写”使用同一偏移位置。
- 使用lseek获取文件大小
- 使用lseek拓展文件大小:要想使文件大小真正拓展,必须引起IO操作。使用 truncate 函数,直接拓展文件。例:int ret = truncate(“dict.cp”, 250);
whence:
- SEEK_SET 偏移量设为离文件开头offset个字节
- SEEK_CUR 偏移量设为其当前值加offset(offest可正负,正时向后偏移offset,负时向前偏移offset)
- SEEK_END 偏移量设为文件长度加offset(offest可正负)
7. 文件描述符
- 对内核而言,所有打开的文件都通过文件描述符引用。
- 文件描述符是一个非负整数。
- 当打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描述符。
文件描述符:
- 0 - STDIN_FILENO
- 1 - STDOUT_FILENO
- 2 - STDERR_FILENO
8. 代码练习
8.1 文件复制
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int fdSrc;
int fdDes;
char *buff = NULL;
if(argc != 3) {
printf("param error!");
exit(-1);
}
fdSrc = open(argv[1], O_RDWR);
int size = lseek(fdSrc, 0, SEEK_END); // 获取文件大小
lseek(fdSrc, 0, SEEK_SET); // 恢复偏移
// printf("%d",size);
buff = (char *) malloc(sizeof(char) * size + 1);
int n_read = read(fdSrc, buff, size);
fdDes = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, 0600);
int n_write = write(fdDes, buff, strlen(buff));
close(fdSrc);
close(fdDes);
return 0;
}
8.2 修改配置文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int fdSrc;
char *buff = NULL;
if(argc != 2) {
printf("param error!");
exit(-1);
}
fdSrc = open(argv[1], O_RDWR);
int size = lseek(fdSrc, 0, SEEK_END);
lseek(fdSrc, 0, SEEK_SET);
printf("%d",size);
buff = (char *) malloc(sizeof(char) * size + 1);
int n_read = read(fdSrc, buff, size);
char *s = strstr(buff, "LENG=");
if (s == NULL) {
printf("not found\n");
exit(-1);
}
s = s + strlen("LENG=");
*s = '5';
lseek(fdSrc, 0, SEEK_SET);
int n_write = write(fdSrc, buff, strlen(buff));
close(fdSrc);
return 0;
}
8.3 向文件写入整数
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main() {
int fd;
int data = 99;
int data2 = 0;
fd = open("./file2", O_RDWR);
int n_write = write(fd, &data, sizeof(int));
lseek(fd, 0, SEEK_SET);
int n_read = read(fd, &data2, sizeof(int));
printf("read %d\n", data2);
close(fd);
return 0;
}
8.4 向文件写入结构体
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
struct Test {
int a;
char c;
};
int main() {
int fd;
struct Test data[2] = {{100, 'a'},{80, 'b'}};
struct Test data2[2];
fd = open("./file2", O_RDWR);
int n_write = write(fd, &data, sizeof(struct Test) * 2);
lseek(fd, 0, SEEK_SET);
int n_read = read(fd, &data2, sizeof(struct Test) * 2);
printf("read %d, %c\n", data2[0].a, data2[0].c);
printf("read %d, %c\n", data2[1].a, data2[1].c);
close(fd);
return 0;
}