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

Linux文件编程——读写结构体、链表等其他类型的数据

在 Linux 文件编程中, openreadwriteclose等函数,本质上的读写内容是一个无类型的指针,所以其也可以读写整型、数组、结构体、链表等不同类型的数据。

SYNOPSIS
#include <unistd.h>ssize_t write(int fd, const void *buf, size_t count);
SYNOPSIS
#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);

我们可以看到读写的buf的类型都是void *,即他只是一个无类型的指针,本质上就是一个地址,和数据类型没关系,因此我们可以读写其他类型的数据。

1. 整型数据

写入整型数据

在 Linux 文件编程中,使用低级文件 I/O 函数写入整型数据时,需要先打开文件,然后将整型变量的地址和大小传递给 write 函数。write 函数会将整型数据以二进制形式写入文件。

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>int main() {int fd = open("data.bin", O_WRONLY | O_CREAT | O_TRUNC, 0644); // 打开文件用于写入if (fd == -1) {perror("Error opening file");return 1;}int num = 42;if (write(fd, &num, sizeof(num)) != sizeof(num)) { // 写入整型数据perror("Error writing to file");}close(fd); // 关闭文件return 0;
}
  • open 函数用于打开文件,O_WRONLY 表示以写入模式打开文件,O_CREAT 表示如果文件不存在则创建文件,O_TRUNC 表示如果文件已存在则清空文件内容。

  • write 函数的第一个参数是文件描述符,第二个参数是指向要写入的数据的指针(这里是整型变量 num 的地址),第三个参数是要写入的字节数(这里是 sizeof(num))。

  • 如果 write 函数返回的值不等于要写入的字节数,说明写入操作失败。

读取整型数据

读取整型数据时,同样需要先打开文件,然后使用 read 函数将数据读取到一个整型变量中。

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>int main() {int fd = open("data.bin", O_RDONLY); // 打开文件用于读取if (fd == -1) {perror("Error opening file");return 1;}int num;if (read(fd, &num, sizeof(num)) != sizeof(num)) { // 读取整型数据perror("Error reading from file");} else {printf("Read number: %d\n", num); // 输出读取的整型数据}close(fd); // 关闭文件return 0;
}
  • open 函数使用 O_RDONLY 参数以只读模式打开文件。

  • read 函数的第一个参数是文件描述符,第二个参数是指向存储读取数据的缓冲区的指针(这里是整型变量 num 的地址),第三个参数是要读取的字节数(这里是 sizeof(num))。

  • 如果 read 函数返回的值不等于要读取的字节数,说明读取操作失败。

2. 数组数据

写入数组数据

写入数组数据时,需要将整个数组的内存地址和大小传递给 write 函数。

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>int main() {int fd = open("array.bin", O_WRONLY | O_CREAT | O_TRUNC, 0644); // 打开文件用于写入if (fd == -1) {perror("Error opening file");return 1;}int arr[] = {1, 2, 3, 4, 5}; // 定义一个整型数组size_t size = sizeof(arr) / sizeof(arr[0]); // 计算数组大小if (write(fd, arr, sizeof(arr)) != sizeof(arr)) { // 写入数组perror("Error writing to file");}close(fd); // 关闭文件return 0;
}
  • sizeof(arr) 计算整个数组的大小(以字节为单位)。

  • write 函数将整个数组的内容写入文件。如果返回值不等于数组的大小,说明写入操作失败。

读取数组数据

读取数组数据时,需要将文件中的数据读取到一个数组中。

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>int main() {int fd = open("array.bin", O_RDONLY); // 打开文件用于读取if (fd == -1) {perror("Error opening file");return 1;}int arr[5]; // 定义一个足够大的数组来存储读取的数据if (read(fd, arr, sizeof(arr)) != sizeof(arr)) { // 读取数组perror("Error reading from file");} else {for (int i = 0; i < 5; i++) {printf("arr[%d] = %d\n", i, arr[i]); // 输出读取的数组元素}}close(fd); // 关闭文件return 0;
}
  • read 函数将文件中的数据读取到数组 arr 中。如果返回值不等于数组的大小,说明读取操作失败。

  • 使用循环输出数组中的每个元素。

3. 结构体数据

定义结构体
typedef struct {int id;char name[50];float score;
} Student;
写入结构体数据

写入结构体数据时,需要将结构体变量的地址和大小传递给 write 函数。

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>int main() {int fd = open("students.bin", O_WRONLY | O_CREAT | O_TRUNC, 0644); // 打开文件用于写入if (fd == -1) {perror("Error opening file");return 1;}Student s = {1, "Alice", 95.5}; // 定义一个结构体变量if (write(fd, &s, sizeof(Student)) != sizeof(Student)) { // 写入结构体perror("Error writing to file");}close(fd); // 关闭文件return 0;
}
  • sizeof(Student) 计算结构体的大小。

  • write 函数将整个结构体的内容写入文件。如果返回值不等于结构体的大小,说明写入操作失败。

读取结构体数据

读取结构体数据时,需要将文件中的数据读取到一个结构体变量中。

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>int main() {int fd = open("students.bin", O_RDONLY); // 打开文件用于读取if (fd == -1) {perror("Error opening file");return 1;}Student s;if (read(fd, &s, sizeof(Student)) != sizeof(Student)) { // 读取结构体perror("Error reading from file");} else {printf("ID: %d, Name: %s, Score: %.2f\n", s.id, s.name, s.score); // 输出读取的结构体内容}close(fd); // 关闭文件return 0;
}
  • read 函数将文件中的数据读取到结构体变量 s 中。如果返回值不等于结构体的大小,说明读取操作失败。

  • 使用 printf 输出结构体的各个字段。

4. 链表数据

定义链表节点
typedef struct Node {int data;struct Node *next;
} Node;
写入链表数据

写入链表数据时,需要逐个节点将数据写入文件。

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>void writeLinkedList(Node *head, const char *filename) {int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd == -1) {perror("Error opening file");return;}Node *current = head;while (current != NULL) {if (write(fd, &current->data, sizeof(int)) != sizeof(int)) { // 写入节点数据perror("Error writing to file");break;}current = current->next;}close(fd);
}
  • 使用 open 打开文件,O_WRONLY 表示以写入模式打开文件,O_CREAT 表示如果文件不存在则创建文件,O_TRUNC 表示如果文件已存在则清空文件内容。

  • 遍历链表,逐个节点将数据写入文件。每次写入一个 int 类型的数据。

  • 如果 write 函数返回的值不等于 sizeof(int),说明写入操作失败。

读取链表数据

读取链表数据时,需要逐个节点从文件中读取数据,并动态分配内存来构建链表。

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>Node* readLinkedList(const char *filename) {int fd = open(filename, O_RDONLY);if (fd == -1) {perror("Error opening file");return NULL;}Node *head = NULL, *tail = NULL;int data;while (read(fd, &data, sizeof(int)) == sizeof(int)) { // 读取节点数据Node *newNode = (Node *)malloc(sizeof(Node));newNode->data = data;newNode->next = NULL;if (head == NULL) {head = newNode;tail = newNode;} else {tail->next = newNode;tail = newNode;}}close(fd);return head;
}
  • 使用 open 打开文件,O_RDONLY 表示以只读模式打开文件。

  • 使用循环逐个读取文件中的数据。每次读取一个 int 类型的数据。

  • 每次读取到一个数据后,动态分配一个新节点,并将其添加到链表中。

  • 如果 read 函数返回的值不等于 sizeof(int),说明读取操作失败,循环结束。

注意事项

  1. 文件描述符的管理

    使用低级文件 I/O 函数时,需要手动管理文件描述符的打开和关闭,确保不会出现资源泄漏。在程序结束时,务必调用 close 函数关闭文件描述符。
  2. 错误处理

    低级文件 I/O 函数的错误处理通常依赖于 errno。在读写操作后,可以通过检查返回值是否为预期值来判断操作是否成功。如果返回值为 -1,可以通过 perrorstrerror(errno) 获取错误信息。
  3. 链表的动态内存管理

    在读取链表时,需要动态分配内存来构建链表,并在使用完毕后释放内存,以避免内存泄漏。
http://www.xdnf.cn/news/6032.html

相关文章:

  • 9.9 Ollama私有化部署Mistral 7B全指南:命令行交互到API集成全流程解析
  • 格雷希尔G10和G15系列自动化快速密封连接器,适用于哪些管件的密封,以及它们相关的特性有哪些?
  • 参考UTD的上市公司供应链信息数据库(2017-2022)
  • 深度学习模型在目标检测任务中的前向传播(forward)和反向传播(backward)过程
  • 基于STM32、HAL库的TLV320AIC3101IRHBR音频接口芯片驱动程序设计
  • NovaMSS v1.40音乐源分离工具,一键提取伴奏人声贝斯鼓点分离音轨等
  • 交流充电桩IEC 61851-1和IEC 61851-21-2标准测试项目
  • Deno、Bun、Node.js 性能对比与选型指南
  • C++23 ranges::range_adaptor_closure:程序定义的范围适配器闭包的辅助类
  • flutter Stream 有哪两种订阅模式。
  • 从新手到高手:全面解析 AI 时代的「魔法咒语」——Prompt
  • Hue面试内容整理-后端框架
  • C++11异步编程 --- async
  • 多目应用:三目相机在汽车智能驾驶领域的应用与技术创新
  • Generative Diffusion Prior for Unified Image Restoration and Enhancement论文阅读
  • Kafka原理深度剖析
  • 【大模型LLM学习】MiniCPM的注意力机制学习
  • LVS+keepalived实战案例
  • 2025-05-13 表征学习
  • Datawhale 5月llm-universe 第1次笔记
  • 从Aurora 架构看数据库计算存储分离架构
  • ArcGIS、InVEST与RUSLE在水土流失模拟及分析中的实践技术
  • C# 高级编程:Expression表达式
  • 记录vsCode连接gitee并实现项目拉取和上传
  • 力扣Hot100(Java版本)
  • 如何学习VBA_3.3.3 VBA程序写好后,如何进行调试,直到程序运行
  • 力扣-543.二叉树的直径
  • 每周靶点分享:Nectin-4、CDH6及文献分享
  • 网络协议分析 实验四 ICMPv4与ICMPv6
  • 紫光同创FPGA实现AD7606数据采集转UDP网络传输,提供PDS工程源码和技术支持和QT上位机