Read() возвращает неверное количество байтов, считанных на некоторых системах

Я пытаюсь решить проблему чтения файлов в старой системе.

Это 32-битное Windows-приложение, протестированное и запущенное только на Windows7/SP1/64-битных системах, все из которых имеют одинаковые SP, SDK и IDE. IDE - VS2010/SP1.

Вот код, о котором идет речь:

#define ANZSEL 20

int ii, bfil, ipos;

if ((bfil = open("Z:\\whatever.bla", O_RDONLY, 0)) == -1) { goto end; } // please don't complain about this; it just here because I didn't want to rephrase the if == -1 above and because it a legacy codebase; i also tried with UNC paths by the way with the same result

 ii = read(bfil, &some_struct_instance, sizeof(some_struct));
 ipos = _lseek(bfil,0,SEEK_CUR); // ipos shows the correct position here, ie. sizeof(some_struct)
 if (ii == sizeof(some_struct)) {

 ii = read(bfil, &another_struct_instance, sizeof(another_struct)*ANZSEL); // ii here sometimes shows 15 instead of sizeof(another_struct)*ANZSEL
 ipos = _lseek(bfil,0,SEEK_CUR); // ipos always shows the correct value of sizeof(some_struct) + sizeof(another_struct)*ANZSEL
 if (ii == sizeof(another_struct)*ANZSEL) {

 // should always come here as long as the files' long enough

Итак, как вы можете видеть, это должно быть простой старый прямой двоичный код, читаемый в некоторые структуры. Я мог заметить, что когда я создаю файл и сначала очищаю структуру с memset/Zeromem, чтобы также "инициализировать" все padding-байты с 0x00 вместо 0xCC (который является способом Microsoft пометки mem в режиме отладки как не инициализированный stack mem) проблема исчезает в системе, где раньше она не вела себя правильно.

Хотя мне кажется ясным, как я могу "правильно" решить проблему - укажите O_BINARY в open() как

if ((bfil = open("Z:\\whatever.bla", O_RDONLY|O_BINARY, 0)) == -1)

Я не знаю, почему это может вести себя по-другому. Я попытался просмотреть источники open() и read() в обеих системах, но поскольку я редко имею доступ к единственной системе, в которой проблема может быть воспроизведена, я еще ничего не смог найти.

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

1 ответ

Обычно это происходит, когда файл содержит значение 0x1a (aka control-Z). Как и MS-DOS перед этим, Windows интерпретирует control-Z как сигнализацию конца текстового файла, поэтому, когда вы открываете файл в текстовом режиме и достигает 0x1a, он просто перестает читать.

Как вы уже нашли, открытие файла в двоичном режиме устраняет проблему - 0x1a больше не интерпретируется как сигнализация конца файла.

licensed under cc by-sa 3.0 with attribution.