【问题标题】:Using lseek system call in C to read a structure written in a file在 C 中使用 lseek 系统调用来读取写入文件中的结构
【发布时间】:2019-09-22 19:43:22
【问题描述】:

我已将结构 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() 从文件中读取特定学生的信息来定位文件指针吗?

【问题讨论】:

  • if 语句以 5 个右括号结束时,您实际上可能会考虑重构代码。
  • 此外,您无法保证read 将实际读取所有请求的字节。这就是为什么它返回正确读取的字节数(您忽略了)。

标签: c linux unix operating-system


【解决方案1】:

有多个问题:

在你的写作循环中,你可能想为一个索引为 i 的学生写数据。此外,您应该使用 struct Student 的大小,而不是所有学生数据的完整大小。

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

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

这里&amp;stud[i]指向学生i的数据。使用sizeof(struct Student) 时,仅写入一名学生的数据。

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

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

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

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

如果文件描述引用normal file,则此行可以正常工作。

man 2 read 说:

系统保证读取请求的字节数,如果 描述符引用了一个剩下那么多字节的普通文件 在文件结尾之前,但在其他情况下。

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

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

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);
}

【讨论】:

  • 好点。即使引用了normal file,也最好始终处理部分读取。我添加了更多信息。
  • 感谢各位的帮助。 Stephan 发布的解决方案非常棒,而且效果很好。再次感谢。
猜你喜欢
  • 2017-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多