IO进线程(二)——文件IO

本文详细介绍了文件I/O操作,包括标准IO和POSIX方式下的open、close、read、write和lseek函数,以及目录操作,如打开、关闭、读取和复制。此外,还展示了如何在文件操作中加入命令行参数,并实现了文件的加密和解密功能。
摘要由CSDN通过智能技术生成

1. 文件IO

标准IO:

  1. ANSIC(美国国家学会)
  2. 文件流指针操作文件
  3. 有缓冲区
  4. 高级IO
  5. 适用于普通文件
  6. 标准I0较少系统调用的次数(先缓冲区—系统调用)
  7. c库
  8. 标准I0是在文件IO的基础上封装了缓冲机制;

文件IO

  1. posix 标准
  2. 文件描述符
  3. 无缓冲
  4. 低级IO
  5. 适用于特殊文件
  6. 每次调用文件IO必然发生系统调用
  7. 系统调用的API
open()
read()
write()
close()
lseek()

打开文件open

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
/* 
功能: 打开一个已经存在的文件;
参数:
  pathname: 文件名
  flags: 打开方式
    O_RDONLY 只读
    O_WRONLY 只写
    O_RDWR   读写
返回值: 成功返回一个文件描述符,失败返回-1并设置错误号;
文件描述符是一个非负整数,顺序分配,用来标识文件;
系统默认打开三个文件描述符:
0	标准输入 stdin
1	标准输出 stdout
2	标准错误 stderr

*/

int open(const char *pathname, int flags, mode_t mode);
/*
功能:打开文件,如果文件不存在则创建;
参数:
  pathname:文件路径名
  flags:打开方式和控制选项
    - 例如:O_RDONLY、O_WRONLY、O_RDWR、O_CREAT、O_TRUNC、O_APPEND 等
  mode:文件权限设置(仅当使用O_CREAT选项时有效)
    - 用八进制表示,例如0777
    - 最终权限计算方式:mode & ~umask
返回值:成功返回文件描述符,失败返回-1并设置errno;
注意:创建文件时,必须与O_CREAT选项一起使用,并且需要提供第三个参数mode。
*/

打开一个文件

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd = open("test.txt", O_RDWR | O_CREAT, 0666);
    
    if (fd < 0) {
        perror("open");
        return -1;
    }
    
    printf("打开文件成功......\n");
    printf("fd = %d\n", fd);
    
    close(fd);
    
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd = open("test.txt", O_RDWR); // 以读写方式打开文件"test.txt"

    if (fd < 0) {
        perror("open"); // 如果打开失败,打印错误信息
        return 1; // 返回错误码1
    }

    printf("文件成功打开\n");

    close(fd); // 关闭文件描述符

    return 0; // 返回成功
}

文件的关闭close

#include <unistd.h>

int close(int fd);
/*
功能:关闭已打开的文件描述符;
参数:
  fd:文件描述符
返回值:成功返回0,失败返回-1并设置errno;
*/
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd = open("test.txt", O_RDWR);
    
    if (fd < 0) {
        perror("open");
        return -1;
    }
    
    printf("文件打开成功\n");
    
    close(fd);
    
    return 0;
}

文件的读取read

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);
{
/*
功能:从一个打开的文件读取内容;
参数:
  fd:文件描述符
  buf:存储读取内容的缓冲区
  count:要读取的字节数
返回值:实际读取的字节数,读到文件末尾返回0,如果出错则返回-1并设置errno;
*/
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    char buffer[100]; // 用于存储读取的内容的缓冲区
    int fd = open("test.txt", O_RDONLY); // 打开文件test.txt以读取方式
    
    if (fd < 0) {
        perror("open");
        return -1;
    }
    
    ssize_t num_bytes_read = read(fd, buffer, sizeof(buffer)); // 读取文件内容到缓冲区
    
    if (num_bytes_read < 0) {
        perror("read");
        close(fd);
        return -1;
    }
    
    printf("读取的内容:%s\n", buffer); // 打印读取的内容
    
    close(fd);
    
    return 0;
}

读取文件的前十个字节并输出到终端

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define BUFFER_SIZE 10

int main() {
    char buffer[BUFFER_SIZE + 1]; // 用于存储读取的内容的缓冲区,多一个字节用于存储字符串结尾的'\0'
    int fd = open("test.txt", O_RDONLY); // 打开文件test.txt以读取方式
    
    if (fd < 0) {
        perror("open");
        return -1;
    }
    
    ssize_t num_bytes_read = read(fd, buffer, BUFFER_SIZE); // 读取文件的前十个字节到缓冲区
    
    if (num_bytes_read < 0) {
        perror("read");
        close(fd);
        return -1;
    }
    
    buffer[num_bytes_read] = '\0'; // 添加字符串结尾的'\0'
    printf("文件的前十个字节:%s\n", buffer); // 打印读取的内容
    
    close(fd);
    
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd = open("test.txt", O_RDONLY);
    
    if (fd < 0) {
        perror("open");
        return 1;
    }
    
    printf("文件打开成功......\n");
    printf("文件描述符 = %d\n", fd);
    
    char buf[32] = {0}; // 初始化缓冲区
    
    // 读取文件的内容
    int ret = read(fd, buf, 10);
    
    if (ret < 0) {
        perror("read");
        return 1;
    } else if (ret == 0) {
        printf("已读取到文件末尾\n");
        return 1;
    }
    
    printf("实际读取的字节数 = %d\n", ret);
    printf("读取的内容:%s\n", buf);
    
    close(fd);
    
    return 0;
}

文件的写入(输出)write

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);
/*
功能:向一个打开的文件写入内容;
参数:
  fd:文件描述符
  buf:保存要写入的数据的空间首地址
  count:预计要写入的字节数
返回值:实际写入的字节数,如果出错则返回-1并设置errno
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    char buf[32] = {0};
    printf(">:\n");
    fgets(buf, sizeof(buf), stdin);

    if (buf[strlen(buf) - 1] == '\n') {
        buf[strlen(buf) - 1] = '\0';
    }

    // 如果文件不存在则创建并以写的方式打开,如果文件存在则以写的方式打开并清空文件内容
    int fd = open("test.txt", O_CREAT | O_WRONLY | O_TRUNC, 0666);
    if (fd < 0) {
        perror("open");
        return 1;
    }

    // 将buf里的数据写入到文件当中
    write(fd, buf, sizeof(buf));
    close(fd);

    return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    char buf[32];
    
    // 提示用户输入内容
    printf(">:\n");
    
    // 从标准输入读取用户输入的内容
    fgets(buf, sizeof(buf), stdin);

    // 检查是否读取到了换行符,如果是,则将其替换为字符串结束符
    if (buf[strlen(buf) - 1] == '\n') {
        buf[strlen(buf) - 1] = '\0';
    }

    // 打开或创建文件test.txt,以写的方式打开并清空文件内容
    int fd = open("test.txt", O_CREAT | O_WRONLY | O_TRUNC, 0666);
    if (fd < 0) {
        perror("open");
        return -1;
    }

    // 将用户输入的内容写入到文件中
    write(fd, buf, strlen(buf));
    
    // 关闭文件
    close(fd);

    // 重新打开文件以读取数据
    fd = open("test.txt", O_RDONLY);
    if (fd < 0) {
        perror("open");
        return -1;
    }

    // 定义一个缓冲区用于读取文件中的数据
    char data[32] = {0};
    
    // 读取文件中的数据
    int ret = read(fd, data, sizeof(data));
    if (ret < 0) {
        perror("read");
        return -1;
    } else if (ret == 0) {
        printf("读取到文件的末尾\n");
        return -1;
    }

    // 输出读取到的文件中的数据
    printf("data: %s\n", data);

    return 0;
}


文件的定位lseek

#include <sys/types.h>

off_t lseek(int fd, off_t offset, int whence);
/*
功能:实现对文件的定位。
参数:
  fd:文件描述符。
  offset:偏移量,可以为正数或负数,表示相对于 whence 参数的偏移量。
  whence:指定偏移量的基准位置。
    - SEEK_SET:从文件开头开始计算偏移量。
    - SEEK_CUR:从当前文件指针位置开始计算偏移量。
    - SEEK_END:从文件末尾开始计算偏移量。
返回值:返回文件指针相对于文件开头的偏移量,如果出错则返回-1并设置errno。
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    char buf[32];

    // 提示用户输入内容
    printf(">:\n");

    // 从标准输入读取用户输入的内容
    fgets(buf, sizeof(buf), stdin);

    // 检查是否读取到了换行符,如果是,则将其替换为字符串结束符
    if (buf[strlen(buf) - 1] == '\n') {
        buf[strlen(buf) - 1] = '\0';
    }

    // 打开或创建文件 test.txt,以读写的方式打开并清空文件内容
    int fd = open("test.txt", O_CREAT | O_RDWR | O_TRUNC, 0666);
    if (fd < 0) {
        perror("open");
        return -1;
    }

    // 将 buf 里的数据写入到文件中
    write(fd, buf, strlen(buf));

    // 将文件内部指针指向开头
    if (-1 == lseek(fd, 0, SEEK_SET)) {
        perror("lseek");
        return -1;
    }

    // 重新定义一个缓冲区用于读取文件中的数据
    char data[32] = {0};

    // 读取文件中的数据
    int ret = read(fd, data, sizeof(data));
    if (ret < 0) {
        perror("read");
        return -1;
    }

    // 输出读取到的文件中的数据
    printf("data: %s\n", data);

    return 0;
}

目录

目录的打开

#include <sys/types.h>
#include <dirent.h>

DIR *opendir(const char *name);
/*
功能:打开目录。
参数:
  name:目录路径。
返回值:成功打开目录则返回一个指向目录的指针(DIR 类型),失败则返回 NULL,并设置 errno。
*/
#include <stdio.h>
#include <dirent.h>

int main() {
    // 打开目录
    DIR *dir = opendir(".");

    // 检查目录是否成功打开
    if (dir == NULL) {
        perror("opendir");
        return -1;
    }

    // 读取目录中的内容
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        printf("%s\n", entry->d_name);
    }

    // 关闭目录
    closedir(dir);

    return 0;
}

目录的关闭

#include <sys/types.h>
#include <dirent.h>

int closedir(DIR *dirp);
/*
功能:关闭目录流指针。
参数:
  dirp:目录流指针。
返回值:成功关闭目录流指针则返回0,失败返回-1,并设置 errno。
*/
#include <stdio.h>
#include <dirent.h>

int main() {
    // 打开目录
    DIR *dir = opendir(".");

    // 检查目录是否成功打开
    if (dir == NULL) {
        perror("opendir");
        return -1;
    }

    // 读取目录中的内容
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        printf("%s\n", entry->d_name);
    }

    // 关闭目录
    if (closedir(dir) == -1) {
        perror("closedir");
        return -1;
    }

    return 0;
}

获取目录里的文件

#include <dirent.h>

struct dirent *readdir(DIR *dirp);
/*
功能:读取目录中的内容。
参数:
  dirp:目录流指针。
返回值:成功读取到目录中的下一个目录项则返回一个指向该目录项的指针(`struct dirent *` 类型),如果到达目录末尾或者出错则返回 NULL。
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h> // 包含 DIR 结构体和 opendir 函数的头文件

int main(int argc, char *argv[]) {
    // 检查命令行参数是否正确
    if (argc != 2) {
        printf("Usage: %s dirname\n", argv[0]); // 正确的格式为:程序名 目录名
        return -1;
    }

    // 打开目录
    DIR *dirp = opendir(argv[1]);
    if (dirp == NULL) {
        perror("opendir"); // 打印出错信息
        return -1;
    }

    // 读取目录
    struct dirent *dp;
    while ((dp = readdir(dirp)) != NULL) {
        printf("%s\n", dp->d_name); // 输出每个目录项的名称
    }

    // 关闭目录
    closedir(dirp);

    return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h> // 包含 DIR 结构体和相关函数的头文件

int main(int argc, char *argv[]) {
    // 检查命令行参数是否正确
    if (argc != 2) {
        printf("Usage: %s dirname\n", argv[0]); // 正确的格式为:程序名 目录名
        return -1;
    }

    // 打开目录
    DIR *dirp = opendir(argv[1]);
    if (dirp == NULL) {
        perror("opendir"); // 打印出错信息
        return -1;
    }

    // 读取目录中的内容并输出
    struct dirent *dp;
    while ((dp = readdir(dirp)) != NULL) {
        // 检查目录项名称是否以点开头,如果是则跳过
        if (dp->d_name[0] == '.') {
            continue;
        }
        printf("%s\n", dp->d_name); // 输出每个目录项的名称
    }

    // 关闭目录
    closedir(dirp);

    return 0;
}

1. 实现文件的拷贝,并加入命令行参数

#include <stdio.h>

int main(int argc, char *argv[]) {
    // 检查命令行参数是否正确
    if (argc != 3) {
        printf("Usage: %s source_file destination_file\n", argv[0]);
        return -1;
    }

    // 打开源文件
    FILE *source_file = fopen(argv[1], "r");
    if (source_file == NULL) {
        perror("fopen source_file");
        return -1;
    }

    // 打开目标文件
    FILE *destination_file = fopen(argv[2], "w");
    if (destination_file == NULL) {
        perror("fopen destination_file");
        fclose(source_file);
        return -1;
    }

    // 逐字符读取源文件,并写入目标文件
    int ch;
    while ((ch = fgetc(source_file)) != EOF) {
        fputc(ch, destination_file);
    }

    // 关闭文件
    fclose(source_file);
    fclose(destination_file);

    printf("File copied successfully.\n");
    return 0;
}

2. 实现文件的加密和解密

#include <stdio.h>

void encrypt_decrypt_file(const char *input_file, const char *output_file, int key) {
    FILE *input = fopen(input_file, "r");
    FILE *output = fopen(output_file, "w");

    if (input == NULL || output == NULL) {
        perror("fopen");
        return;
    }

    int ch;
    while ((ch = fgetc(input)) != EOF) {
        ch += key; // 加密或解密操作,加密时 key 为正,解密时 key 为负
        fputc(ch, output);
    }

    fclose(input);
    fclose(output);
}

int main(int argc, char *argv[]) {
    if (argc != 4) {
        printf("Usage: %s input_file output_file key\n", argv[0]);
        return -1;
    }

    const char *input_file = argv[1];
    const char *output_file = argv[2];
    int key = atoi(argv[3]); // 将命令行参数转换为整数

    encrypt_decrypt_file(input_file, output_file, key);

    printf("Operation completed successfully.\n");
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嵌入式石油工程师

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

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

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

打赏作者

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

抵扣说明:

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

余额充值