Использование системного вызова lseek в C для чтения структуры, записанной в файле - PullRequest
1 голос
/ 22 сентября 2019

Я записал структуру 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 () для позиционирования указателя файла?

1 Ответ

1 голос
/ 23 сентября 2019

Существует несколько проблем:

Внутри цикла записи вы можете записать данные для одного учащегося с индексом i .Также вы должны использовать размер структуры Student, а не полный размер данных для всех студентов.

В коде это будет выглядеть так:

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

Здесь &stud[i] указывает на данные студента i .При использовании sizeof(struct Student) записываются только данные для одного учащегося.

При считывании данных в память необходимо правильно рассчитать количество байтов.Пара скобок отсутствует.Он должен выглядеть следующим образом:

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

Если вы хотите вывести только одного студента, вы должны использовать , если вместо , тогда как :

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...