ftell/fseek завершается ошибкой при приближении к концу файла

Чтение текстового файла (который является членом PDS FB 80)

hFile = fopen(filename,"r");

и дошли до того места в файле, где осталась только пустая строка.

FilePos = ftell(hFile);

Затем прочитайте последнюю строку, которая содержит только символ '\n'.

fseek(hFile, FilePos, SEEK_SET);

терпит неудачу с: -

errno=(27) EDC5027I The position specified to fseek() was invalid.

Позиция, указанная для fseek(), была возвращена ftell() несколькими строками ранее. Он имеет значение 841 в конкретном случае ошибки, который я видел. При проверке в отладчике это же значение вернул ftell несколькими строками ранее. Он не был поврежден.

Тот же код работает в других позициях в файле и дает сбой только в том месте, где остается одна пустая строка для чтения, когда позиция запоминается.

Мое понимание того, как должно работать ftell/fseek, кратко отражено в другом ответе на SO.

Значение, возвращаемое ftell в текстовом потоке, не имеет предсказуемой связи с количеством символов, которые вы уже прочитали. Единственное, на что вы можете положиться, это то, что вы можете использовать его впоследствии в качестве аргумента смещения для fseek или fseeko, чтобы вернуться к той же позиции в файле.

Казалось бы, я не могу полагаться на то единственное, на что я должен быть в состоянии положиться.

У меня вопрос, почему fseek терпит неудачу таким образом?


person Morag Hughson    schedule 16.07.2020    source источник
comment
Попробуйте с export _EDC_ZERO_RECLEN=Y.   -  person Milos Lalovic    schedule 16.07.2020
comment
Интересно, я попробую - наличие одного '\n' считается нулем?   -  person Morag Hughson    schedule 18.07.2020
comment
Поразмыслив еще немного, поток открывается в текстовом или двоичном режиме?   -  person meat    schedule 19.07.2020
comment
@meat - как указано в вопросе, это текстовый файл, который открывается с помощью r. Будет обновлен текст вопроса, чтобы отразить это.   -  person Morag Hughson    schedule 20.07.2020
comment
@MilosLlovic - наконец-то я попробовал ваше предложение, но это не имело никакого значения.   -  person Morag Hughson    schedule 28.07.2020


Ответы (2)


Поскольку в z/OS есть несколько уникальных форматов файлов, вы можете найти ответ в этом статья Центра знаний.

Учитывая, что вы обрабатываете элемент PDS, я подозреваю, что это ввод-вывод уровня записи, который обрабатывается иначе, чем поток ввода-вывода, который более распространен в распределенных реализациях.

person Hogstrom    schedule 16.07.2020
comment
Файловые функции POSIX поддерживают чтение из последовательных источников (в данном случае члена PDS) в потоковом режиме. - person meat; 16.07.2020
comment
@Hogstrom - обратите внимание, я не использую параметр режима открытия type=record. так что это не запись уровня ввода-вывода. Член PDS — это всего лишь небольшой текстовый файл, фиксированный блок 80, ничего сложного. - person Morag Hughson; 20.07.2020

Я не знаю, почему fseek терпит неудачу таким образом, но если вы обычно используете ftell для получения позиции, а затем fseek для перехода к этой позиции, я настоятельно рекомендую вместо этого использовать fgetpos и fsetpos для ввода-вывода набора данных. Вы не только избежите обнаруженной проблемы, но и повысите производительность для определенных характеристик набора данных.

person meat    schedule 16.07.2020
comment
Спасибо - на самом деле это то, что я сделал в то же время, но я хотел бы также разобраться в проблеме, поскольку это, безусловно, не кажется мне правильным. - person Morag Hughson; 18.07.2020