Linux系统编程-文件操作

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

应用场景:

  1. 文件的“读”、“写”使用同一偏移位置。
  2. 使用lseek获取文件大小
  3. 使用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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不知所云,

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值