Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Чтение бинарного файла


Автор: Master01 30.1.2011, 17:58
Всем Доброго Дня,

Есть такая задачка - дан бинарный файл, содержащий значения разного типа - int, float и пр. Структура файла известна, так что когда и что читать ясно.
Вопрос в том чем этот файл читать? Потоки ifstream явно для этого не предназначены, потому что всё что я нашёл это чтение символов-байтов через read. А код вида

Код

boost::uint16_t chunk_id = 0;
file.read((char*)&chunk_id, sizeof(boost::uint16_t));


я как-то писать не расположен smile. Неужели в ifstrem нету чего-то вроде -

Код

template<typename _T>
void read_numeric(_T& data)
{
   read((char*)&data, sizeof(_T));
}


Я не знаю, может так и должно быть... Для меня это  просто неожиданность. До этого бинарные файлы читать не приходилось.

Может есть способ получше?

Заранее Спасибо.

Автор: boostcoder 30.1.2011, 18:15
учитывая тот факт, что файл писался через попу(наверное не вами), странно ожидать удобного его чтения ;)
так что, так вам и придется его читать, через попу ;)

Автор: EnergoHokum 31.1.2011, 08:22
Цитата

Потоки ifstream явно для этого не предназначены, потому что всё что я нашёл это чтение символов-байтов через read

Открывай поток с модификатором std::ios::binary, читай данные через http://cplusplus.com/reference/iostream/istream/operator%3E%3E/ (можешь перегрузить его для своих типов данных). Гулять по файлу туда-сюда можно функцией http://cplusplus.com/reference/iostream/istream/seekg/. Выяснить позицию, до которой догулял -- функцией http://cplusplus.com/reference/iostream/istream/tellg/. Ну и так далее. Ничего невозможного здесь нет.

Автор: Master01 31.1.2011, 14:17
Цитата(EnergoHokum @ 31.1.2011,  08:22)
Цитата

Потоки ifstream явно для этого не предназначены, потому что всё что я нашёл это чтение символов-байтов через read

Открывай поток с модификатором std::ios::binary, читай данные через http://cplusplus.com/reference/iostream/istream/operator%3E%3E/ (можешь перегрузить его для своих типов данных). Гулять по файлу туда-сюда можно функцией http://cplusplus.com/reference/iostream/istream/seekg/. Выяснить позицию, до которой догулял -- функцией http://cplusplus.com/reference/iostream/istream/tellg/. Ну и так далее. Ничего невозможного здесь нет.


EnergoHokum, Я просто пробовал читать через operator >>. В результате у меня поток переводился в состояние bad, а в переменную ничего не считывалось.
Я, собственно, потому и поднял тему, так как поначалу тоже ожидал, что так должно работать.  
Может я и ошибаюсь в своих рассуждениях, но, насколько я понимаю, operator >> это форматированный ввод, что не совсем подходит для случая если файл бинарный?
Открывал поток, с тем флагом как вы указали.

Добавлено через 3 минуты и 36 секунд
а, ну да, если перегрузить свой оператор >> , то работать будет, согласен. Мне  больше не понятно почему эти операторы уже не перегружены под такие нужды?

Автор: xvr 31.1.2011, 14:35
Цитата(Master01 @  31.1.2011,  14:17 Найти цитируемый пост)
 Мне  больше не понятно почему эти операторы уже не перегружены под такие нужды? 
Они перегружен под нужды текстового (форматированного) чтения. А открытие потока в режиме binary вовсе не означает, что вся работа с ним немедленно станет бинарной. Это всего лишь означает, что система не будет по своему усмотрению никак модифицировать данные, помещаемые (или читаемые) из потока. Например не будет преобразовывать '\n' в '\r\n' (и обратно)

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


Автор: boostcoder 31.1.2011, 14:38
Цитата(Master01 @  31.1.2011,  14:17 Найти цитируемый пост)
не понятно почему эти операторы уже не перегружены под такие нужды?

наверное потому, что в таком случае станет невозможным определить, как использовать операторы ввода-вывода, для работы с текстовыми или бинарными данными ;)

Автор: Earnest 31.1.2011, 17:34
Цитата(Master01 @  30.1.2011,  18:58 Найти цитируемый пост)
Неужели в ifstrem нету чего-то вроде -

template<typename _T>
void read_numeric(_T& data)
{
   read((char*)&data, sizeof(_T));
}

Есть, конечно, именно read и используется. Только если _T это POD. Обычно фиксированный бинарный формат и состоит из нек. кол-ва последовательно записанных POD'ов, возможно, с вариантами. Если влом все время писать sizeof, то используй свой шаблон.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)