c - 在 C 中使用 lseek 系统调用读取文件中写入的结构

标签 c linux unix operating-system

我已经将 Student 结构写入一个文件并将整个结构读取到控制台。 现在,我想重新定位文件指针以读取有关特定学生的信息。我只想使用系统调用来写入文件(read()、write()、lseek())

这是用于将结构写入文件的代码:

struct Student{
char name[20];
char dob[20];
int id;
char sex[20];
};

struct Student stud[size];

 for (int i = 0;i<size;i++){
   printf("Enter name:");
   scanf("%s",stud[i].name);

   printf("Enter date of birth:");
   scanf("%s",stud[i].dob);

   printf("Enter id: ");
   scanf("%d",&stud[i].id);

   printf("Enter sex: ");
   scanf("%s",stud[i].sex);

   n =write(fd,&stud,sizeof(stud));
 }

这是读取写入文件的整个结构的代码:

struct Student studread[5];
int j=0;
while (((n =read(fd,&studread, sizeof(studread))))){
   printf("%s\n",studread[j].name);
   printf("%s\n",studread[j].dob);
   printf("%d\n",studread[j].id);
   printf("%s\n",studread[j].sex);
   j++;
}

下面是读取特定学生信息的代码:

struct Student  pread;
printf("Enter a position: ");
scanf("%d",&pos);

nobytes =sizeof(struct Student) * pos-1;  
position = lseek(fd,nobytes,SEEK_SET);

while (size=read(fd,&pread,sizeof(pread))){
    printf("%s\n",pread.name);
    printf("%s\n",pread.dob);
    printf("%d\n",pread.id);
    printf("%s\n",pread.sex);
}

你能帮我使用 lseek() 定位文件指针从文件中读取特定学生的信息吗?

最佳答案

存在多个问题:

在您的写入循环中,您可能希望为索引为 i 的一名学生写入数据。此外,您应该使用 Student 结构的大小,而不是所有学生数据的完整大小。

在代码中它看起来像这样:

n = write(fd, &stud[i], sizeof(struct Student));

这里&stud[i]指向学生i的数据。当使用 sizeof(struct Student) 时,只写入一个学生的数据。

将数据读入内存时,必须正确计算字节数。缺少一对括号。它应该看起来像:

nobytes = sizeof(struct Student) * (pos - 1);

如果你只想输出一个学生,你应该使用 if 而不是 while:

if (read(fd, &pread, sizeof(pread)) == sizeof(pread)) {

如果文件描述引用的是普通文件,则此行工作正常。

man 2 read 说:

The system guarantees to read the number of bytes requested if the descriptor references a normal file that has that many bytes left before the end-of-file, but in no other case.

但如果使用网络文件系统,它可能已经失败了。

所以最好使用类似的东西:

ssize_t bytes_read = 0;
ssize_t n;
while ((n = read(fd, &pread + bytes_read,  sizeof(pread) - bytes_read)) > 0) {
    bytes_read += n;
}

因此,如果 read 只返回部分结果,它也能正常工作。

不要忘记事后检查读取的字节数。它可能看起来像:

if(bytes_read == sizeof(pread)) {
    printf("%s\n", pread.name);
    printf("%s\n", pread.dob);
    printf("%d\n", pread.id);
    printf("%s\n", pread.sex);
} else {
    printf("not enough data");
    exit(1);
}

关于c - 在 C 中使用 lseek 系统调用读取文件中写入的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58052828/

相关文章:

c - 以下程序的时间复杂度是多少?

c - C 中的斐波那契数对于 1 - 18 非常有效,但 19 根本不起作用

c - 查找最大数的数组指针

linux - Rsyslog 消息的 tcpdump 信息中有奇怪的条目

linux - 如何使用 UNIX 命令获取具有最大年龄的人的姓名

unix - Bmon 遇到段错误

linux - 在 shell 脚本中拆分并重命名拆分的文件

c - 尝试使用调用 stat 的 ctime 返回值对 c 中的结构数组进行排序

c - 使用 fork 和 execvp 启动/停止/etc/init.d/中的服务不起作用

c - "Segmentation fault"当 `rmmod` 或 `modprobe -r`