当前位置: 首页 > news >正文

linux----文件访问(c语言)

linux文件访问相关函数

  1. 打开文件函数 - open
    • 函数原型int open(const char *pathname, int flags, mode_t mode);
    • 参数说明
      • pathname:这是要打开的文件的路径名,可以是绝对路径或者相对路径。例如,"/home/user/file.txt"或者"./data.dat"
      • flags:用于指定打开文件的方式,常见的标志有:
        • O_RDONLY:以只读方式打开文件。
        • O_WRONLY:以只写方式打开文件。
        • O_RDWR:以可读可写方式打开文件。
        • O_CREAT:如果文件不存在,则创建文件。通常和mode参数一起使用。
        • O_APPEND:以追加方式打开文件,写入的数据会添加在文件末尾。
      • mode:当使用O_CREAT标志创建文件时,这个参数用于指定文件的权限。它是一个八进制数,例如0644表示所有者有读写权限,所属组和其他用户有读权限。
    • 返回值
      • 成功时返回一个非负整数,这个整数是文件描述符(File Descriptor)。文件描述符用于后续对文件的读写等操作。例如,012分别是标准输入、标准输出和标准错误输出的文件描述符,而新打开的文件描述符通常是大于等于3的整数。
      • 失败时返回-1,并且会设置errno来指示错误原因,常见的错误原因可能是文件不存在、权限不足等。可以通过perror函数来打印错误信息。
    • 示例代码
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main() {int fd;// 以只读方式打开文件,如果文件不存在则返回错误fd = open("test.txt", O_RDONLY);if (fd == -1) {perror("打开文件失败");return 1;}// 在这里可以进行文件的读取操作// 关闭文件if (close(fd) == -1) {perror("关闭文件失败");return 1;}return 0;
}
  1. 读取文件函数 - read
    • 函数原型ssize_t read(int fd, void *buf, size_t count);
    • 参数说明
      • fd:这是之前通过open函数打开文件得到的文件描述符。
      • buf:这是一个指向缓冲区的指针,用于存储读取到的文件内容。缓冲区的大小应该足够容纳要读取的数据。例如,可以定义一个字符数组char buffer[1024];来作为缓冲区。
      • count:这是要读取的字节数。例如,如果count10,则最多读取10个字节的文件内容。
    • 返回值
      • 成功时返回实际读取到的字节数。如果返回值小于count,可能是已经到达文件末尾或者被信号中断等原因。例如,返回0表示已经到达文件末尾。
      • 失败时返回-1,并且会设置errno来指示错误原因,常见的错误原因可能是文件描述符无效、权限不足等。
    • 示例代码(续接上面open函数的示例)
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main() {int fd;char buffer[1024];ssize_t num_read;// 以只读方式打开文件,如果文件不存在则返回错误fd = open("test.txt", O_RDONLY);if (fd == -1) {perror("打开文件失败");return 1;}// 读取文件内容num_read = read(fd, buffer, sizeof(buffer));if (num_read == -1) {perror("读取文件失败");close(fd);return 1;} else if (num_read == 0) {printf("文件为空。\n");} else {buffer[num_read] = '\0';printf("读取到的内容:%s", buffer);}// 关闭文件if (close(fd) == -1) {perror("关闭文件失败");return 1;}return 0;
}
  1. 写入文件函数 - write
    • 函数原型ssize_t write(int fd, const void *buf, size_t count);
    • 参数说明
      • fd:文件描述符,和read函数中的fd类似,是通过open函数打开文件得到的。
      • buf:这是一个指向包含要写入数据的缓冲区的指针。例如,如果要写入一个字符串,可以定义char data[] = "Hello, World!";,然后将data作为buf参数。
      • count:这是要写入的字节数。例如,对于上面的字符串datacount可以是strlen(data)
    • 返回值
      • 成功时返回实际写入的字节数。如果返回值小于count,可能是磁盘空间不足、被信号中断等原因。
      • 失败时返回-1,并且会设置errno来指示错误原因,常见的错误原因可能是文件描述符无效、权限不足等。
    • 示例代码(写入一个新文件)
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main() {int fd;char data[] = "这是写入文件的测试内容。";// 以只写方式打开文件,如果文件不存在则创建文件fd = open("new_file.txt", O_WRONLY | O_CREAT, 0644);if (fd == -1) {perror("打开文件失败");return 1;}// 写入文件内容ssize_t num_written = write(fd, data, strlen(data));if (num_written == -1) {perror("写入文件失败");close(fd);return 1;}printf("写入了 %zd 个字节。\n", num_written);// 关闭文件if (close(fd) == -1) {perror("关闭文件失败");return 1;}return 0;
}
  1. 关闭文件函数 - close
    • 函数原型int close(int fd);
    • 参数说明
      • fd:这是要关闭的文件的文件描述符,是之前通过open函数打开文件得到的。
    • 返回值
      • 成功时返回0
      • 失败时返回-1,并且会设置errno来指示错误原因,常见的错误原因可能是文件描述符无效等。
    • 重要性
      • 关闭文件是一个重要的操作,它可以释放文件描述符资源,确保数据的完整性。如果不关闭文件,可能会导致文件损坏、资源泄漏等问题。例如,在写入文件后,如果没有正确关闭文件,数据可能没有完全写入磁盘,导致数据丢失。
  2. 文件打开与创建相关函数
    • open()函数
      • 功能:用于打开或创建文件。它是最基本的文件操作函数之一。
      • 参数
        • pathname:文件路径名,如"/home/user/documents/file.txt"。可以是绝对路径或相对路径。
        • flags:指定文件打开方式。例如,O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(读写)。还有其他一些标志,如O_CREAT(若文件不存在则创建)、O_APPEND(追加模式打开)等。
        • mode:当使用O_CREAT标志时,用于指定新创建文件的权限,如0644(所有者读写,组和其他用户只读)。
      • 返回值:成功返回文件描述符(非负整数),失败返回 - 1,并设置errno
    • creat()函数
      • 功能:创建一个新文件。它等效于open(pathname, O_WRONLY|O_CREAT|O_TRUNC, mode)
      • 参数
        • pathname:文件路径。
        • mode:文件权限模式。
      • 返回值:成功返回文件描述符,失败返回 - 1。不过在现代Linux编程中,open()函数使用更广泛,因为它功能更灵活。
  3. 文件读取相关函数
    • read()函数
      • 功能:从打开的文件中读取数据。
      • 参数
        • fd:文件描述符,由open()等函数返回。
        • buf:指向存储读取数据的缓冲区的指针,例如char buffer[1024];
        • count:希望读取的字节数。
      • 返回值:成功时返回实际读取的字节数。如果返回0,表示已读到文件末尾;返回 - 1表示出错,同时设置errno
    • pread()函数
      • 功能:从指定文件偏移量处读取数据,读取操作不会改变文件偏移量。
      • 参数
        • fd:文件描述符。
        • buf:缓冲区指针。
        • count:读取字节数。
        • offset:文件中的偏移量,从该位置开始读取。
      • 返回值:和read()函数类似,成功返回实际读取字节数,0表示文件末尾, - 1表示出错。
  4. 文件写入相关函数
    • write()函数
      • 功能:将数据写入打开的文件。
      • 参数
        • fd:文件描述符。
        • buf:指向包含要写入数据的缓冲区的指针。
        • count:要写入的字节数。
      • 返回值:成功时返回实际写入的字节数,可能小于count(如磁盘空间不足);返回 - 1表示出错,同时设置errno
    • pwrite()函数
      • 功能:在指定文件偏移量处写入数据,写入操作不会改变文件偏移量。
      • 参数
        • fd:文件描述符。
        • buf:包含要写入数据的缓冲区指针。
        • count:写入字节数。
        • offset:文件中的偏移量,在该位置写入。
      • 返回值:和write()函数类似,成功返回实际写入字节数, - 1表示出错。
  5. 文件定位相关函数
    • lseek()函数
      • 功能:移动文件读写指针的位置,用于在文件中随机访问。
      • 参数
        • fd:文件描述符。
        • offset:偏移量,正数表示向文件尾方向移动,负数表示向文件头方向移动。
        • whence:指定偏移量的相对位置,SEEK_SET(从文件开头)、SEEK_CUR(从当前位置)、SEEK_END(从文件末尾)。
      • 返回值:成功返回新的文件偏移量(从文件开头计算的字节数),失败返回 - 1。
  6. 文件属性获取相关函数
    • stat()函数
      • 功能:获取文件的状态信息,如文件大小、权限、所有者等。
      • 参数
        • pathname:文件路径。
        • buf:指向struct stat结构体的指针,用于存储文件状态信息。
      • 返回值:成功返回0,失败返回 - 1,并设置errnostruct stat结构体包含文件的多种属性,如st_size(文件大小)、st_mode(文件权限和类型)等。
    • fstat()函数
      • 功能:和stat()类似,但它获取的是已打开文件(通过文件描述符)的状态信息。
      • 参数
        • fd:文件描述符。
        • buf:指向struct stat结构体的指针。
      • 返回值:成功返回0,失败返回 - 1。
  7. 文件关闭相关函数
    • close()函数
      • 功能:关闭一个打开的文件,释放文件描述符等资源。
      • 参数
        • fd:要关闭的文件的文件描述符。
      • 返回值:成功返回0,失败返回 - 1。关闭文件非常重要,不关闭可能导致资源泄漏、数据丢失等问题。
  8. 目录文件操作相关函数(用于访问目录中的文件)
    • opendir()函数
      • 功能:打开一个目录,返回一个指向DIR结构体的指针,用于后续对目录的操作。
      • 参数
        • pathname:目录路径。
      • 返回值:成功返回DIR结构体指针,失败返回NULL
    • readdir()函数
      • 功能:读取打开目录中的一个条目(文件或子目录),返回一个指向struct dirent结构体的指针,包含条目的名称等信息。
      • 参数
        • dirpopendir()返回的DIR结构体指针。
      • 返回值:成功返回struct dirent结构体指针,若已读完目录或出错则返回NULL
    • closedir()函数
      • 功能:关闭之前由opendir()打开的目录,释放相关资源。
      • 参数
        • dirpDIR结构体指针。
      • 返回值:成功返回0,失败返回 - 1。

以下是上述各Linux文件访问相关函数的代码案例,展示了它们在实际编程中的具体用法:
在这里插入图片描述

1. open()函数示例

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>int main() {int fd;// 尝试以只读方式打开一个已存在的文件fd = open("test.txt", O_RDONLY);if (fd == -1) {perror("打开文件失败");return 1;}printf("成功打开文件,文件描述符为: %d\n", fd);// 关闭文件if (close(fd) == -1) {perror("关闭文件失败");return 1;}return 0;
}

在这个示例中,首先尝试以只读方式打开名为test.txt的文件,如果打开成功,会打印出获得的文件描述符,最后关闭该文件。

2. creat()函数示例

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>int main() {int fd;// 使用creat创建一个新文件,权限设置为0644(所有者读写,组和其他用户只读)fd = creat("new_file.txt", 0644);if (fd == -1) {perror("创建文件失败");return 1;}printf("成功创建文件,文件描述符为: %d\n", fd);// 关闭文件if (close(fd) == -1) {perror("关闭文件失败");return 1;}return 0;
}

此代码尝试创建一个名为new_file.txt的新文件,指定了文件权限为0644,创建成功后打印文件描述符并关闭文件。

3. read()函数示例(结合open()函数使用)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>#define BUFFER_SIZE 1024int main() {int fd;ssize_t num_read;char buffer[BUFFER_SIZE];// 以只读方式打开文件fd = open("test.txt", O_RDONLY);if (fd == -1) {perror("打开文件失败");return 1;}// 从文件中读取数据到缓冲区num_read = read(fd, buffer, sizeof(buffer));if (num_read == -1) {perror("读取文件失败");close(fd);return 1;} else if (num_read == 0) {printf("文件已读完(到达文件末尾)\n");} else {buffer[num_read] = '\0';  // 添加字符串结束符printf("读取到的内容: %s\n", buffer);}// 关闭文件if (close(fd) == -1) {perror("关闭文件失败");return 1;}return 0;
}

这段代码先打开一个文件,然后使用read函数从文件中读取数据到定义的缓冲区,根据read函数的返回值判断读取情况,并做相应处理,最后关闭文件。

4. pread()函数示例(结合open()函数使用)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>#define BUFFER_SIZE 1024int main() {int fd;ssize_t num_read;char buffer[BUFFER_SIZE];off_t offset = 10;  // 从文件偏移量为10的位置开始读取// 以只读方式打开文件fd = open("test.txt", O_RDONLY);if (fd == -1) {perror("打开文件失败");return 1;}// 使用pread从指定偏移量处读取数据num_read = pread(fd, buffer, sizeof(buffer), offset);if (num_read == -1) {perror("读取文件失败");close(fd);return 1;} else if (num_read == 0) {printf("已读到文件末尾\n");} else {buffer[num_read] = '\0';printf("从偏移量 %ld 处读取到的内容: %s\n", offset, buffer);}// 关闭文件if (close(fd) == -1) {perror("关闭文件失败");return 1;}return 0;
}

该示例先打开文件,然后利用pread函数从指定的文件偏移量位置开始读取数据,读取后根据返回值处理数据并关闭文件。

5. write()函数示例(结合open()函数使用)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>#define DATA "这是要写入文件的数据"int main() {int fd;ssize_t num_written;// 以只写方式打开文件,如果文件不存在则创建fd = open("output.txt", O_WRONLY | O_CREAT, 0644);if (fd == -1) {perror("打开文件失败");return 1;}// 将数据写入文件num_written = write(fd, DATA, strlen(DATA));if (num_written == -1) {perror("写入文件失败");close(fd);return 1;}printf("成功写入 %zd 个字节到文件\n", num_written);// 关闭文件if (close(fd) == -1) {perror("关闭文件失败");return 1;}return 0;
}

这里先打开(或创建)一个文件,再使用write函数将特定的数据写入文件,根据返回值判断写入情况,最后关闭文件。

6. pwrite()函数示例(结合open()函数使用)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>#define DATA "新的数据"
#define OFFSET 20  // 在文件偏移量为20的位置写入数据int main() {int fd;ssize_t num_written;// 以读写方式打开文件fd = open("test_write.txt", O_RDWR);if (fd == -1) {perror("打开文件失败");return 1;}// 使用pwrite在指定偏移量处写入数据num_written = pwrite(fd, DATA, strlen(DATA), OFFSET);if (num_written == -1) {perror("写入文件失败");close(fd);return 1;}printf("成功在偏移量 %d 处写入 %zd 个字节到文件\n", OFFSET, num_written);// 关闭文件if (close(fd) == -1) {perror("关闭文件失败");return 1;}return 0;
}

代码先打开一个文件用于读写,接着通过pwrite函数在指定的文件偏移量位置写入数据,处理写入结果后关闭文件。

7. lseek()函数示例(结合open()函数使用)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>int main() {int fd;off_t new_offset;// 以读写方式打开文件fd = open("test_lseek.txt", O_RDWR);if (fd == -1) {perror("打开文件失败");return 1;}// 将文件读写指针移动到文件末尾new_offset = lseek(fd, 0, SEEK_END);if (new_offset == -1) {perror("移动文件指针失败");close(fd);return 1;}printf("文件指针已移动到文件末尾,当前偏移量为: %ld\n", new_offset);// 关闭文件if (close(fd) == -1) {perror("关闭文件失败");return 1;}return 0;
}

此示例打开一个文件后,使用lseek函数将文件读写指针移动到文件末尾,获取并打印新的偏移量,最后关闭文件。

8. stat()函数示例

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>int main() {struct stat file_stat;// 获取文件状态信息if (stat("test.txt", &file_stat) == -1) {perror("获取文件状态信息失败");return 1;}// 打印文件大小(字节数)printf("文件大小为: %ld 字节\n", file_stat.st_size);// 打印文件权限(八进制表示)printf("文件权限(八进制): %o\n", file_stat.st_mode & 0777);return 0;
}

该代码通过stat函数获取指定文件的状态信息,然后从struct stat结构体中提取文件大小和权限等信息并进行打印。

9. fstat()函数示例(结合open()函数使用)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>int main() {int fd;struct stat file_stat;// 以只读方式打开文件fd = open("test.txt", O_RDONLY);if (fd == -1) {perror("打开文件失败");return 1;}// 获取已打开文件的状态信息if (fstat(fd, &file_stat) == -1) {perror("获取文件状态信息失败");close(fd);return 1;}// 打印文件大小(字节数)printf("文件大小为: %ld 字节\n", file_stat.st_size);// 关闭文件if (close(fd) == -1) {perror("关闭文件失败");return 1;}return 0;
}

代码先打开一个文件,然后使用fstat函数获取该已打开文件的状态信息,从中获取文件大小并打印,最后关闭文件。

10. close()函数示例(在上述各示例中都有体现,以下单独简单示意)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>int main() {int fd = 3;  // 假设这里有一个文件描述符为3的已打开文件(实际应用中通常由open等函数获取)if (close(fd) == -1) {perror("关闭文件失败");return 1;}printf("文件已成功关闭\n");return 0;
}

这个简单示例演示了使用close函数关闭一个给定文件描述符对应的文件,根据返回值判断关闭是否成功。

11. 目录文件操作相关函数示例

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>int main() {DIR *dp;struct dirent *ep;// 打开当前目录dp = opendir(".");if (dp == NULL) {perror("打开目录失败");return 1;}// 读取目录中的条目并打印文件名while ((ep = readdir(dp))!= NULL) {printf("文件名: %s\n", ep->d_name);}// 关闭目录if (closedir(dp) == -1) {perror("关闭目录失败");return 1;}return 0;
}

这段代码首先使用opendir函数打开当前目录,然后通过readdir函数循环读取目录中的文件和子目录条目,并打印它们的名称,最后使用closedir函数关闭打开的目录。

实践案例

  1. 简单的文件复制程序
    • 案例描述
      • 编写一个C程序,实现将一个文件的内容复制到另一个文件中。这个案例涉及到文件的打开、读取和写入操作。
    • 代码实现
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define BUFFER_SIZE 1024
int main(int argc, char *argv[]) {int source_fd, destination_fd;ssize_t num_read, num_written;char buffer[BUFFER_SIZE];// 检查命令行参数是否正确if (argc!= 3) {fprintf(stderr, "用法: %s <源文件> <目标文件>\n", argv[0]);return 1;}// 打开源文件,以只读方式source_fd = open(argv[1], O_RDONLY);if (source_fd == -1) {perror("打开源文件失败");return 1;}// 打开目标文件,以写入方式,如果不存在则创建,权限为0644destination_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);if (destination_fd == -1) {perror("打开目标文件失败");close(source_fd);return 1;}// 从源文件读取数据并写入目标文件while ((num_read = read(source_fd, buffer, sizeof(buffer))) > 0) {num_written = write(destination_fd, buffer, num_read);if (num_written == -1) {perror("写入目标文件失败");close(source_fd);close(destination_fd);return 1;}}if (num_read == -1) {perror("读取源文件失败");close(source_fd);close(destination_fd);return 1;}// 关闭文件if (close(source_fd) == -1) {perror("关闭源文件失败");close(destination_fd);return 1;}if (close(destination_fd) == -1) {perror("关闭目标文件失败");return 1;}return 0;
}
  • 案例分析
    • 首先,程序通过open函数分别打开源文件和目标文件,注意打开方式的选择。然后,使用read函数从源文件读取数据到缓冲区,再通过write函数将缓冲区的数据写入目标文件。在循环过程中,不断重复读取和写入操作,直到read函数返回0,表示已经读取完源文件的内容。最后,关闭源文件和目标文件。
  1. 文件内容统计程序
    • 案例描述
      • 编写一个脚本(以Bash脚本为例),用于统计一个文本文件中单词的数量。这个案例涉及到文件的读取和简单的文本处理。
    • 代码实现
#!/bin/bash
if [ $# -ne 1 ]; thenecho "用法: $0 <文件名>"exit 1
fi
filename="$1"
if [! -f "$filename" ]; thenecho "文件不存在"exit 1
fi
word_count=$(cat "$filename" | wc -w)
echo "文件 $filename 中的单词数量为: $word_count"
  • 案例分析
    • 脚本首先检查命令行参数的个数是否正确,然后判断指定的文件是否存在。如果文件存在,使用cat命令读取文件内容,并通过管道|将内容传递给wc -w命令,wc -w用于统计单词数量。最后将统计结果输出。
  1. 文件权限修改程序
    • 案例描述
      • 编写一个C程序,用于修改指定文件的权限。这个案例涉及到文件属性的操作。
    • 代码实现
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char *argv[]) {if (argc!= 3) {fprintf(stderr, "用法: %s <文件名> <权限模式(八进制)>\n", argv[0]);return 1;}const char *filename = argv[1];mode_t mode = (mode_t) strtol(argv[2], NULL, 8);if (chmod(filename, mode) == -1) {perror("修改权限失败");return 1;}return 0;
}
  • 案例分析
    • 程序首先检查命令行参数的个数是否正确,然后将第二个参数(以八进制表示的权限模式)转换为mode_t类型。接着使用chmod函数来修改指定文件的权限。如果chmod函数返回 - 1,表示修改权限失败,程序会输出错误信息。
  1. 文件搜索程序
    • 案例描述
      • 编写一个Python程序,在指定目录及其子目录下搜索指定文件名的文件。这个案例涉及到目录的遍历和文件的检查。
    • 代码实现
import osdef search_file(directory, filename):for root, dirs, files in os.walk(directory):for file in files:if file == filename:print(os.path.join(root, file))if __name__ == "__main__":directory = input("请输入要搜索的目录: ")filename = input("请输入要搜索的文件名: ")search_file(directory, filename)
  • 案例分析
    • 程序定义了一个search_file函数,使用os.walk函数来遍历指定目录及其子目录。os.walk返回一个三元组(root, dirs, files),其中root是当前遍历的目录路径,dirs是当前目录下的子目录列表,files是当前目录下的文件列表。在循环中,检查每个文件的名称是否与目标文件名相同,如果相同,则输出文件的完整路径。

用open()函数实现一个简单的文本编辑器

以下是一个使用C语言中的open()函数以及其他相关文件操作函数实现的简单文本编辑器示例,它可以实现创建新文件、打开已有文件、写入内容、读取内容以及保存修改等基本功能(这里只是一个简单的演示,没有复杂的文本编辑界面和功能,主要聚焦在文件操作层面)。

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>#define MAX_BUFFER_SIZE 1024// 函数声明
void create_file(const char *filename);
void open_file(int *fd, const char *filename);
void write_to_file(int fd, const char *content);
void read_file(int fd);
void save_file(int fd, const char *filename);
void close_file(int fd);int main() {int choice, fd = -1;char filename[100];char content[MAX_BUFFER_SIZE];while (1) {printf("\n简单文本编辑器功能菜单:\n");printf("1. 创建新文件\n");printf("2. 打开现有文件\n");printf("3. 写入内容到文件\n");printf("4. 读取文件内容\n");printf("5. 保存文件\n");printf("6. 关闭文件并退出\n");printf("请输入你的选择: ");scanf("%d", &choice);switch (choice) {case 1:printf("请输入要创建的文件名: ");scanf("%s", filename);create_file(filename);break;case 2:printf("请输入要打开的文件名: ");scanf("%s", filename);open_file(&fd, filename);break;case 3:if (fd == -1) {printf("请先打开或创建一个文件。\n");continue;}printf("请输入要写入文件的内容(一行内容,按回车键结束): ");scanf("%s", content);write_to_file(fd, content);break;case 4:if (fd == -1) {printf("请先打开一个文件。\n");continue;}read_file(fd);break;case 5:if (fd == -1) {printf("请先打开或创建一个文件。\n");continue;}save_file(fd, filename);break;case 6:if (fd!= -1) {close_file(fd);}return 0;default:printf("无效的选择,请重新输入。\n");}}return 0;
}// 创建新文件的函数
void create_file(const char *filename) {int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd == -1) {perror("创建文件失败");return;}close(fd);printf("文件 %s 创建成功。\n", filename);
}// 打开文件的函数
void open_file(int *fd, const char *filename) {*fd = open(filename, O_RDWR);if (*fd == -1) {perror("打开文件失败");return;}printf("文件 %s 打开成功。\n", filename);
}// 写入内容到文件的函数
void write_to_file(int fd, const char *content) {ssize_t num_written = write(fd, content, strlen(content));if (num_written == -1) {perror("写入文件失败");return;}printf("成功写入 %zd 个字节到文件。\n", num_written);
}// 读取文件内容的函数
void read_file(int fd) {char buffer[MAX_BUFFER_SIZE];ssize_t num_read = read(fd, buffer, sizeof(buffer));if (num_read == -1) {perror("读取文件失败");return;} else if (num_read == 0) {printf("文件为空或已读到文件末尾。\n");} else {buffer[num_read] = '\0';printf("文件内容如下:\n%s\n", buffer);}
}// 保存文件的函数(这里简单的重新写入覆盖原文件内容,可优化为更复杂的保存逻辑)
void save_file(int fd, const char *filename) {// 先关闭文件close(fd);// 再以只写方式打开,覆盖原内容写入fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd == -1) {perror("保存文件失败");return;}char buffer[MAX_BUFFER_SIZE];lseek(fd, 0, SEEK_SET);ssize_t num_read = read(fd, buffer, sizeof(buffer));if (num_read!= -1 && num_read > 0) {buffer[num_read] = '\0';ssize_t num_written = write(fd, buffer, strlen(buffer));if (num_written == -1) {perror("保存文件时写入内容失败");close(fd);return;}}close(fd);printf("文件保存成功。\n");
}// 关闭文件的函数
void close_file(int fd) {if (close(fd) == -1) {perror("关闭文件失败");return;}printf("文件已关闭。\n");
}

以下是对这个代码的详细说明:

1. 整体结构和主函数逻辑

  • 程序通过一个无限循环展示功能菜单,让用户选择相应的操作,包括创建文件、打开文件、写入内容、读取内容、保存文件以及关闭文件并退出等选项。
  • 根据用户输入的不同选择,调用相应的函数来执行具体的文件操作。在进行某些操作(如写入、读取、保存等)前,会先判断文件是否已经正确打开(通过文件描述符是否为 - 1 来判断),若未打开则提示用户先打开或创建文件。

2. 各个功能函数介绍

  • create_file函数
    • 使用open()函数以O_WRONLY | O_CREAT | O_TRUNC模式打开指定文件名的文件,这意味着如果文件不存在则创建它,若存在则截断(清空)其原有内容,权限设置为0644(所有者读写,所属组和其他用户只读)。
    • 如果open操作成功,获取到文件描述符后,使用close函数关闭文件,因为这里只是创建操作,暂时不需要对文件进行读写,关闭后提示用户文件创建成功;若open失败,则通过perror函数打印错误信息。
  • open_file函数
    • 接收一个指向整数(用于存储文件描述符)的指针和文件名作为参数,使用open()函数以O_RDWR(读写)模式打开文件。
    • 若打开成功,将获取到的文件描述符赋值给传入的指针指向的变量,并提示用户文件打开成功;若打开失败,则通过perror函数打印错误信息。
  • write_to_file函数
    • 接收文件描述符和要写入的内容字符串作为参数,使用write()函数将内容写入文件。
    • 根据write函数的返回值判断写入是否成功,若成功则打印写入的字节数,若失败则通过perror函数打印错误信息。
  • read_file函数
    • 接收文件描述符作为参数,定义一个缓冲区数组,使用read()函数从文件中读取内容到缓冲区。
    • 根据read函数的返回值进行不同处理:返回 - 1 表示读取失败,打印错误信息;返回 0 表示文件为空或已读到文件末尾,给出相应提示;若读取到有效内容,则在缓冲区末尾添加字符串结束符后打印出文件内容。
  • save_file函数
    • 先关闭已打开的文件(因为要重新以写入模式打开覆盖原内容),然后再以O_WRONLY | O_CREAT | O_TRUNC模式打开文件,这样可以确保将当前内存中的内容重新覆盖写入文件(这里只是简单实现了重新写入覆盖,可根据实际需求优化保存逻辑,比如实现追加保存等更复杂的功能)。
    • 通过lseek函数将文件指针移动到文件开头,读取文件现有内容到缓冲区,再将缓冲区内容写回文件(这里同样可以优化,比如考虑部分写入等情况),若写入成功则关闭文件并提示文件保存成功,若出现错误则打印错误信息并关闭文件。
  • close_file函数
    • 接收文件描述符作为参数,使用close()函数关闭文件,根据返回值判断关闭是否成功,若失败则通过perror函数打印错误信息,若成功则提示文件已关闭。

请注意,这个简单文本编辑器只是一个基础的示例,实际应用中的文本编辑器功能要复杂得多,例如支持多行编辑、文本格式处理、光标定位等功能,还需要更好的用户交互界面(如图形界面或者更友好的命令行交互方式等),但这个示例可以帮助理解在Linux环境下如何通过open()等文件操作函数来进行基本的文件读写与管理。 在这里插入图片描述

相关文章:

linux----文件访问(c语言)

linux文件访问相关函数 打开文件函数 - open 函数原型&#xff1a;int open(const char *pathname, int flags, mode_t mode);参数说明&#xff1a; pathname&#xff1a;这是要打开的文件的路径名&#xff0c;可以是绝对路径或者相对路径。例如&#xff0c;"/home/user/…...

源码分析之Openlayers中MousePosition鼠标位置控件

概述 本文主要介绍 Openlayers 中的MousePosition鼠标位置控件&#xff0c;该控件会创建一个元素在页面的右上方用来实时显示鼠标光标的位置坐标。该控件在实际应用很有效&#xff0c;可以实时获取鼠标位置&#xff0c;但是一般控件元素都会自定义。 源码分析 MousePosition…...

以ATTCK为例构建网络安全知识图

ATT&CK&#xff08;Adversarial Tactics, Techniques, and Common Knowledge &#xff09;是一个攻击行为知识库和模型&#xff0c;主要应用于评估攻防能力覆盖、APT情报分析、威胁狩猎及攻击模拟等领域。本文简单介绍ATT&CK相关的背景概念&#xff0c;并探讨通过ATT&a…...

myexcel的使用

参考&#xff1a; &#xff08;1&#xff09;api文档&#xff1a;https://www.bookstack.cn/read/MyExcel-2.x/624d8ce73162300b.md &#xff08;2&#xff09;源代码&#xff1a; https://github.com/liaochong/myexcel/issues 我&#xff1a; &#xff08;1&#xff09;m…...

Unity 上好用的插件

PlayerMaker BehaviorDesigner Cinemachine Timeline Hybrid Addressable AssetBundle Blower Simple Zoom 大地图上缩放和平移使用ScrollRect的好效果实现...

Vivado - 远程调试 + 远程综合实现 + vmWare网络配置 + NFS 文件共享 + 使用 VIO 核

目录 1. 简介 2. VIO 配置 2.1 VIO IP 2.2 VIO 对比 ILA 3. VIO 示例 3.1 Led 3.1.1 工程配置 3.1.2 效果展示 3.2 Key 3.2.1 工程配置 3.2.1 效果展示 3.3 门控触发 3.3.1 工程配置 3.3.2 效果展示 4. 远程调试 4.1 配置目标主机 4.2 配置本机 4.3 vmWare 网…...

双臂机器人

目录 一、双臂机器人简介 二、双臂机器人系统的组成 三、双臂机器人面临的主要挑战 3.1 协调与协同控制问题 3.2 力控制与柔顺性问题 3.3 路径规划与轨迹优化问题 3.4 感知与环境交互 3.5 人机协作问题 3.6 能源与效率问题 3.7 稳定性与可靠性问题 四、双臂机器人…...

【Lua热更新】上篇

Lua 热更新 - 上篇 下篇链接&#xff1a;【Lua热更新】下篇 文章目录 Lua 热更新 - 上篇一、AssetBundle1.理论2. AB包资源加载 二、Lua 语法1. 简单数据类型2.字符串操作3.运算符4.条件分支语句5.循环语句6.函数7. table数组8.迭代器遍历9.复杂数据类型 - 表9.1字典9.2类9.3…...

Ubuntu批量修改文件名

文章目录 批量重命名文件&#xff1a;Ubuntu下使用find命令结合sed和mv参考 批量重命名文件&#xff1a;Ubuntu下使用find命令结合sed和mv 在日常开发和文件管理中&#xff0c;有时我们需要批量重命名一批文件&#xff0c;比如将文件名中的某个特定字符串替换为另一个字符串。…...

食家巷大烤馍:岁月沉淀下的麦香传奇

在繁华都市的街角巷尾&#xff0c;隐藏着许多不为人知的美食宝藏&#xff0c;食家巷大烤馍便是其中之一。它宛如一位低调的美食大师&#xff0c;默默散发着独特的魅力&#xff0c;用最质朴的味道&#xff0c;征服着每一个过往食客的味蕾。 初见食家巷大烤馍&#xff0c;你会被…...

harmony UI组件学习(1)

Image 图片组件 string格式&#xff0c;通常用来加载网络图片&#xff0c;需要申请网络访问权限:ohos.permission.INTERNET Image(https://xxx.png) PixelMap格式&#xff0c;可以加载像素图&#xff0c;常用在图片编辑中 Image(pixelMapobject) Resource格式&#xff0c;加…...

BTP Integration Suite CPI Apache Camel

官网文档&#xff1a; https://help.sap.com/docs/integration-suite/sap-integration-suite/what-is-sap-integration-suite CPI 云集成(CPI)有以下几个特性&#xff1a; SAP Cloud Integration通过消息交换支持端到端流程集成。 它基于Apache软件基金会的开源框架Camel。 …...

vitepress-打包SyntaxError: Element is missing end tag.

一、vitepress打包编译报错Element is missing end tag. 背景&#xff1a; 新增了一些笔记准备上传到git仓库&#xff0c;持续集成部署的时候&#xff0c;控制台报错了&#xff0c;错误信息如下&#xff1a; SyntaxError: Element is missing end tag. 仔细看了下控制台几乎没啥…...

【从零开始入门unity游戏开发之——C#篇21】C#面向对象的封装——`this`扩展方法、运算符重载、内部类、`partial` 定义分部类

文章目录 一、this扩展方法1、扩展方法的基本语法2、使用扩展方法3、扩展方法的注意事项5、扩展方法的限制6、总结 二、运算符重载1、C# 运算符重载2、运算符重载的基本语法3. 示例&#xff1a;重载加法运算符 ()4、使用重载的运算符5、支持重载的运算符6、不能重载的运算符7、…...

Java进程占用的内存有哪些部分?

大家好&#xff0c;我是锋哥。今天分享关于【Java进程占用的内存有哪些部分?】面试题。希望对大家有帮助&#xff1b; Java进程占用的内存有哪些部分? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Java进程在运行时&#xff0c;会将内存划分为多个区域&#xf…...

【华为OD机试真题】【2024年E卷】数值同化-队列BFS(C++/Java/Python)

文章目录 分值&#xff1a;200题目描述思路复杂度分析AC 代码 分值&#xff1a;200 题目描述 存在一个 m * n 的 二维数组只&#xff0c;其成员取值范围为0, 1, 2。其中值为1的元素具备同化特性&#xff0c;每经过1S&#xff0c;将上下左右值为0的元素同化为1。而值为2的元素…...

“魔法糖果盒的秘密:用朴素贝叶斯算法猜糖果颜色”

想象一下&#xff0c;你有一个神奇的糖果盒&#xff0c;这个糖果盒里有两种糖果&#xff1a;红色的和蓝色的。你闭上眼睛&#xff0c;从盒子里拿出一个糖果&#xff0c;然后尝一尝&#xff0c;你想知道这个糖果是红色的还是蓝色的。朴素贝叶斯算法就像是一个魔法规则&#xff0…...

linux中docker命令大全

基本命令 docker pull 拉取镜像 docker pull docker push 推送镜像到DockerRegistry docker push docker images 查看本地镜像 docker images docker rmi 删除本地镜像 docker rmi docker run 创建并运行容器&#xff08;不能重复创建&#xff09; docker run d…...

Python `str.strip()` 的高级用法详解

Python str.strip 的高级用法详解 1. str.strip() 的基本用法2. str.strip() 的高级用法2.1 移除指定字符2.2 移除多个指定字符2.3 移除换行符和制表符2.4 结合正则表达式的高级处理 3. lstrip() 和 rstrip() 的用法3.1 lstrip()&#xff1a;移除左端字符3.2 rstrip()&#xff…...

[蓝桥杯 2019 国 B] 排列数

目录 前言 题解 思路 疑问 解答 前言 对于本篇文章是站在别人的基础之上来写的&#xff0c;对于这道题作为2019年国赛B组的最难的一题&#xff0c;他的难度肯定是不小的&#xff0c;这道题我再一开始接触的时候连思路都没有&#xff0c;也是看了两三遍别人发的题解&#x…...

[bug] StarRocks borker load意向之外的bug

意向之外&#xff0c;又清理之中 背景&#xff1a; StarRocks各方面碾压相同类型的数据库&#xff0c;最近我们要从生成HIVE导历史数据&#xff08;ORC格式&#xff09;到StarRocks&#xff0c;前期小测一下&#xff0c;在测试是没问题&#xff0c;上生产先导2个月的数据&…...

2025年前端面试热门题目——HTML|CSS|Javascript|TS知识

以下是对这些 HTML 面试问题的详细解答&#xff1a; 1. HTML 的 src 和 href 属性有什么区别? src (Source) 属性&#xff1a; 用于嵌入资源&#xff0c;例如图像、脚本或 iframe。加载资源时&#xff0c;当前页面的加载会暂停&#xff0c;直到资源加载完成。常用于 <img&g…...

Linux中部署项目

1.下载JDK17 进入 /usr/local 目录&#xff0c;创建 java 文件夹。并将 JDK17 上传到 java 目录下。 上传成功后&#xff0c;通过cd命令进入Java文件夹目录&#xff0c;解压 JDK17 压缩包&#xff0c;命令 unzip zulu17.44.53-ca-jdk17.0.8.1-linux_x64.zip。 如果报错说 u…...

在 CentOS 上安装 MySQL 8

在 CentOS 上安装 MySQL 8 您可以按照以下步骤操作&#xff1a; 1. 更新系统 首先&#xff0c;更新系统软件包以确保安装的最新版本。 sudo yum update -y 2. 安装 MySQL 8 安装 MySQL 存储库 wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.r…...

gradle项目下载依赖报错

报错信息 Cannot resolve external dependency org.projectlombok:lombok:1.18.36 because no repositories are defined. Required by:project :Possible solution:- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/…...

solon 集成 activemq-client (sdk)

原始状态的 activemq-client sdk 集成非常方便&#xff0c;也更适合定制。就是有些同学&#xff0c;可能对原始接口会比较陌生&#xff0c;会希望有个具体的示例。 <dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-client&l…...

LRU 缓存

LRU 缓存 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0c;否…...

使用ZLMediaKit 开源项目搭建RTSP 服务器

ZLMediaKit 是啥&#xff1f; ZLMediaKit是国人开发的开源C流媒体服务器&#xff0c;同SRS一样是主流的流媒体服务器。 ZLToolKit是基于C11的高性能服务器框架&#xff0c;和ZLMediaKit是同一个作者&#xff0c;ZLMediaKit正是使用该框架开发的。 官网 ZLMediaKit开源地址&…...

数组晨考2day08

1.用一句话描述数组 在内存中 一块连续的空间 存储相同类型的数据 长度是固定的 2.数组各个类型的默认值 整数&#xff1a;0 浮点&#xff1a;0.0 布尔&#xff1a;false 字符&#xff1a;\u0000 其他&#xff1a;null 3.Arrays类toString&#xff0c;copyOf&#xff0c;sort&a…...

《鸿蒙HarmonyOS应用开发从入门到精通(第2版)》简介

《鸿蒙HarmonyOS应用开发从入门到精通&#xff08;第2版&#xff09;》已于近日上市&#xff0c;该书由北京大学出版社出版。距离第1版上市已经过去二年半多。本文希望与读者朋友们分享下这本书里面的大致内容。 封面部分 首先是介绍封面部分。 《鸿蒙HarmonyOS应用开发从入门…...