Форум программистов, компьютерный форум, киберфорум
C (Си)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
4 / 5 / 0
Регистрация: 14.06.2020
Сообщений: 121

Корректное определение конца бинарного файла

30.03.2026, 10:09. Показов 4967. Ответов 60

Студворк — интернет-сервис помощи студентам
Доброго дня, коллеги.
Понял, что практически не работал с "сырыми" бинарниками, в основном писал/читал структурки и поля известной длины, а по файлу перемещался с помощью fseek(). Поэтому никогда не возникало необходимости в детектировании конца файла. В общем, время пришло...

Обычно читаю вот этим (знаю что неоптимальна):
C
1
2
3
4
5
6
7
8
bool _readfile(FILE *F, unsigned char *data, size_t datasize)
{
   // Проверяем указатели
   if(F == NULL || data == NULL) return false;
   // Читаем данные
   for(size_t rdd = 0; rdd < datasize;) rdd += fread(data + rdd, 1 ,datasize - rdd, F);
   return true;           
};
Для использования feof(), как я понял, сгодится такая модификация:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bool t_readfile(FILE *F, unsigned char *data, size_t *datasize)
{
    // Проверяем указатели
    if(F == NULL || data == NULL || datasize == NULL) return false;
    // Проверяем достижение конца файла до запуска цикла
    int eof_check = feof(F);
    if(eof_check > 0 || eof_check == EOF) return false;
    // Читаем данные
    for(size_t toread = *datasize, readed = 0; readed < toread;)
    {
        // Читаем как получается
        readed += fread(data + readed, 1 ,toread - readed, F);
        // Проверка конца файла
        eof_check = feof(F);
        if(eof_check > 0 || eof_check == EOF)
        {
            // Передаем сколько прочитано и ломаемся
            *datasize = readed;
            break;
        }
    }
    return true;
};
Модификация сгодится или нужно что-то другое?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
30.03.2026, 10:09
Ответы с готовыми решениями:

Не корректное исполнение бинарного кода
Добрый день дорогие форумчане. На днях столкнулся с такой проблемой как некорректное открытие...

Создание бинарного дерева из бинарного файла
struct Bin { string name; string city; int players; int score; }; void...

Создание бинарного дерево из бинарного файла
struct Bin { string name; string city; int players; int score; }; void...

60
658 / 411 / 76
Регистрация: 21.09.2008
Сообщений: 1,412
02.04.2026, 18:06
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от peter_irich Посмотреть сообщение
Чем не устраивет, например, функция lseek()?
В стандартах С99, С17, С2х такой функции нет. Может поэтому и не устраивает?
0
Заблокирован
02.04.2026, 18:12
Цитата Сообщение от sharpey Посмотреть сообщение
В стандартах С99, С17, С2х такой функции нет
А это тогда откуда?
lseek(2) System Calls Manual lseek(2)

NAME
lseek - reposition read/write file offset

LIBRARY
Standard C library (libc, -lc)
Ну и не обязаны же в стандарт вообще все функции glibc и т.п. запихивать!
0
Злостный нарушитель
 Аватар для Verevkin
10893 / 5829 / 1288
Регистрация: 12.03.2015
Сообщений: 26,896
02.04.2026, 18:17
Цитата Сообщение от sharpey Посмотреть сообщение
В стандартах С99, С17, С2х такой функции нет. Может поэтому и не устраивает?
Тогда всё сводится к тому, чего надо автору — шашечки или ехать.
Напоминаю, тем, кто забыл, с чего всё начиналось:

0
Злостный нарушитель
 Аватар для Verevkin
10893 / 5829 / 1288
Регистрация: 12.03.2015
Сообщений: 26,896
02.04.2026, 18:22
ИИ гугла выдало такой код:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
 
long getFileSize(const char *filename) 
{
    FILE *fp = fopen(filename, "rb"); // Открытие в бинарном режиме
    if (fp == NULL) return -1; // Ошибка открытия
 
    fseek(fp, 0L, SEEK_END); // Перенос указателя в конец
    long size = ftell(fp);   // Получение текущей позиции (размера)
    fclose(fp);              // Закрытие файла
 
    return size;
}
0
1518 / 533 / 78
Регистрация: 22.09.2023
Сообщений: 1,696
02.04.2026, 18:27
Цитата Сообщение от Verevkin Посмотреть сообщение
Напоминаю, тем, кто забыл, с чего всё начиналось:
"на сарае слово из трех букв написано, а в нем дрова". Начиналось с вот этого:
Цитата Сообщение от Hexpitlel Посмотреть сообщение
Модификация сгодится или нужно что-то другое?
Ответ был дан несколькими участниками: "Нужно что то другое, а именно - не изобретать велосипед".
0
Злостный нарушитель
 Аватар для Verevkin
10893 / 5829 / 1288
Регистрация: 12.03.2015
Сообщений: 26,896
02.04.2026, 18:32
Цитата Сообщение от Dushevny Посмотреть сообщение
"на сарае слово из трех букв написано, а в нем дрова".
Ладно, пойду готовить ужин.
0
Заблокирован
02.04.2026, 19:00
Лучший ответ Сообщение было отмечено Hexpitlel как решение

Решение

Цитата Сообщение от Verevkin Посмотреть сообщение
ИИ гугла выдало такой код
Так это нас возвращает к нашим баранам и проблеме XY.

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

Конкретно на счёт маркера конца файла и функции чтения fread.
fread does not distinguish between end-of-file and error, and callers must use feof and ferror to determine which occurred.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
 
int main()
{  
   {
      FILE *fp = fopen("test.bin", "wb"); // must use binary mode
      fwrite("12345", 1, 5, fp); // writes 5 bytes
      fclose(fp);   
   }
   FILE *fp = fopen("test.bin", "rb"); // must use binary mode
   char buf[16];
   fread(buf, 1, 5, fp); // reads 5 bytes
   if (feof(fp))
      printf("End of File"); // only if we try read more then file contains
   else if (ferror(fp))
      printf("error"); // some error reading
   else
      printf("all data readed"); // all data successful readed
   fclose(fp);
}
Вот от этого поведения и нужно отталкиваться.

Цитата Сообщение от Hexpitlel Посмотреть сообщение
Поэтому никогда не возникало необходимости в детектировании конца файла. В общем, время пришло...
Непонятно. Почему пришло время? Что случилось? Какую задачу решает ТС? Раньше не нужно было обрабатывать ошибки ввода?

Добавлено через 8 минут
Цитата Сообщение от Dushevny Посмотреть сообщение
"Нужно что то другое, а именно - не изобретать велосипед".
Так велосипеды на Си как раз нужны и постоянно.
В данном случае, вероятно, ТС нужен велосипед для обработки ошибок чтения.
Вероятно он читает заранее неопределенное количество записей.
Конец файла в текущем контексте - это и есть одна из ошибок чтения.
Вот эту ошибку ему и нужно корректно обработать.

А что он делает своими функциями в шапке, моя глупая голова не понимать.
1
Злостный нарушитель
 Аватар для Verevkin
10893 / 5829 / 1288
Регистрация: 12.03.2015
Сообщений: 26,896
02.04.2026, 19:27
Цитата Сообщение от 000d60 Посмотреть сообщение
Что бы определить конец бинарного файла, нужно попытаться прочитать данные за концом файла.
Чото я не вижу в коде fread. Передвинуть указатель - это не есть попытка прочитать данные.
Цитата Сообщение от 000d60 Посмотреть сообщение
Вот от этого поведения и нужно отталкиваться.
А я
0
Заблокирован
02.04.2026, 19:49
Verevkin,
Цитата Сообщение от 000d60 Посмотреть сообщение
Так это нас возвращает к нашим баранам и проблеме XY.
После этой фразы, ничего к твоему посту и к тебе лично не имеет.


Нужно было мне какой-то разделитель там поставить, угу
0
 Аватар для peter_irich
371 / 227 / 53
Регистрация: 18.10.2017
Сообщений: 2,436
02.04.2026, 20:24
Я как-то не имел привычки пользоваться fread(), тем более, что речь идёт о бинарных файлах. Всегда устраивали open() и read().
0
Заблокирован
02.04.2026, 20:53
Цитата Сообщение от peter_irich Посмотреть сообщение
Всегда устраивали open() и read().
Что это за звери?
0
Заблокирован
02.04.2026, 21:30
А давайте ТСа дождемся, и поймем-таки, сколько углов должно быть в колесах его велосипеда, приводимого в движение костылями!
1
4 / 5 / 0
Регистрация: 14.06.2020
Сообщений: 121
03.04.2026, 19:58  [ТС]
Цитата Сообщение от 000d60 Посмотреть сообщение
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
int main()
{ 
 {
 FILE *fp = fopen("test.bin", "wb"); // must use binary mode
 fwrite("12345", 1, 5, fp); // writes 5 bytes
 fclose(fp); 
 }
 FILE *fp = fopen("test.bin", "rb"); // must use binary mode
 char buf[16];
 fread(buf, 1, 5, fp); // reads 5 bytes
 if (feof(fp))
 printf("End of File"); // only if we try read more then file contains
 else if (ferror(fp))
 printf("error"); // some error reading
 else
 printf("all data readed"); // all data successful readed
 fclose(fp);
}
Вот эту конструкцию мне нужно было увидеть. Разве только дополнить сохранение в переменную ответа fread() чтобы понимать сколько считалось.

Добавлено через 1 минуту
Где вообще можно взглянуть чего там у fread() под капотом?
0
Заблокирован
03.04.2026, 20:37
Цитата Сообщение от Hexpitlel Посмотреть сообщение
"wb"
Вот такое впервые вижу. Никогда ни в чьем коде не видел "b" — ЗАЧЕМ???
Цитата Сообщение от Hexpitlel Посмотреть сообщение
readed
Про это тоже говорил: в английском такого слова не существует.
Цитата Сообщение от Hexpitlel Посмотреть сообщение
if (feof(fp))
Тут вообще не понимаю: какие могут быть ожидания? В файл записали 5 байт, а потом считали 5 байт. Естественно, будет конец файла...
Но, в очередной раз, задаюсь вопросом: зачем использовать буферизованные операции в подобных случаях? Здесь сразу напрашивается просто открыть при помощи open, а потом при помощи read прочитать!

Добавлено через 47 секунд
Цитата Сообщение от Hexpitlel Посмотреть сообщение
Где вообще можно взглянуть чего там у fread() под капотом?
В исходниках glibc, вестимо…
0
4 / 5 / 0
Регистрация: 14.06.2020
Сообщений: 121
03.04.2026, 20:44  [ТС]
Verevkin, Вариант с fseek() - тоже вариант, я о нем знаю, но вся эта последовательность "открыть, перейти в конец, взять значение, закрыть" у меня вызывает отвращение. Но рабочий вариант, безусловно.
0
Заблокирован
03.04.2026, 20:51
Лучший ответ Сообщение было отмечено Hexpitlel как решение

Решение

Цитата Сообщение от Hexpitlel Посмотреть сообщение
Где вообще можно взглянуть чего там у fread() под капотом?
Можно в исходниках. Например в glibc.
Но зачем?
Есть контракт : https://en.cppreference.com/w/c/io/fread.html
И пример основан на этом же источнике.

Добавлено через 1 минуту
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Тут вообще не понимаю: какие могут быть ожидания? В файл записали 5 байт, а потом считали 5 байт. Естественно, будет конец файла...
Конечно не будет.
Ты смешной.
Eddy_Em, ты пропустил слово "then", плохой с тебя чекер.
0
Заблокирован
03.04.2026, 20:53
Цитата Сообщение от 000d60 Посмотреть сообщение
Конечно не будет.
После чтения пяти байт? Обязательно будет, но с таким «кодом» - да…
0
Заблокирован
03.04.2026, 20:56
Цитата Сообщение от Eddy_Em Посмотреть сообщение
ам уже после считывания пяти байт идет проверка. Естественно, будет EOF!
И при чём тут EOF?
Где он в коде?

Тогда перейди по ссылке для fread и feof и перечитай ещё раз.
https://onlinegdb.com/t_vrL0Syo
0
Заблокирован
03.04.2026, 21:00
Ну, я сам — дятел. Потому как никогда не пользовался fread, и уж, тем паче — feof. Даже для сугубо текстовых файлов: либо mmap, либо обычный read. Но, действительно:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
 
int main(){ 
 FILE *fp = fopen("test.bin", "w");
 fwrite("12345", 1, 5, fp);
 fclose(fp); 
 fp = fopen("test.bin", "r");
 char buf[16];
 fread(buf, 1, 5, fp);
 if (feof(fp))
 printf("End of File\n");
 else if (ferror(fp))
 printf("error\n");
 else
 printf("all data read\n");
 fclose(fp);
}
выдает:
Code
1
2
gcc 1.c && ./a.out 
all data read
Т.е. чтобы таки появился true в feof, нужно сначала до этого feof дойти. Например, так:
C
1
fread(buf, 1, 6, fp);
Code
1
2
gcc 1.c && ./a.out 
End of File
Где логика? Нет логики!

Добавлено через 1 минуту
Цитата Сообщение от 000d60 Посмотреть сообщение
перейди по ссылке
Ты даешь ссылку на нерабочий ресурс, который элементарно не грузится!
0
Заблокирован
03.04.2026, 21:02
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Потому как никогда не пользовался fread, и уж, тем паче — feof.
Тогда зачем так уверенно утверждать что то?
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Ты даешь ссылку на нерабочий ресурс, который элементарно не грузится!
У тебя не грузится - не значит "не рабочий".
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
03.04.2026, 21:02

Рекурсивная функция, которая выведет массив с конца (переворачивать массив не нужно, просто вывод элементов с конца)
Рекурсивная функция, которая выведет массив с конца (переворачивать массив не нужно, просто вывод...

Определение конца файла
помогите пожалуйста определить условие конца файла #include &lt;iostream&gt; #include &lt;cstdio&gt;...

определение конца файла
При чтении не получается выйти из цикла с помощью istream::eof(), было много вариантов причины...

Определение конца файла
Возникают проблемы при чтении бинарного файла, а именно цикл осуществляет лишнюю итерацию и тем...

Определение конца файла , файл задан классом string
Я хочу осуществить чтение файла с обработкой и записью в другой файл. Для этого я хочу использовать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru