LINUX.ORG.RU

а вот подскажите библиотеку/класс c++ для чтения fixed size records

 , ,


1

3
в общем есть файл(ы) типичной структуры:
- мелкий фиксированный заголовок (id. формата, № версии...)
- заголовок чей формат возможно будет зависить от версии
- далее подряд без промежутков идут записи фиксированного размера, формат зависит от версии

не хочется изобретать велосипед, а хочется чё-нить лёгкого без лишней зауми и не тянущего за собой целый фреймворк. Достаточно последовательного доступа на уровне итератора first,next,next..end

ps/ очевидно придётся софтинку переделывать с любимого C на С++;( А всё оттого что некии умники развивая бинарный формат (которому кстати лет больше 10), не просто добавили новых полей в запись, но одно поле в начале каждой записи сделали побольше, а ещё два поменяли местами («так логичнее» блджат). Есть большое подозрение, что на достигнутом они не остановятся, а поддерживать надо всё форматы :(

★★★★★

Ответ на: комментарий от panter_dsd

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

// Подписался на тред

jeuta ★★★★
()
Ответ на: комментарий от jeuta

Какая буфферизация? Какие аллокаторы? Определяется труктура, reinterpret_cast к структуре, передвижение позиции на размер структуры.

panter_dsd ★★★★
()

Вроде там есть FileStream.

FileStream file ....;
int id;
int version;
int records;
file >> id;
file >> version;
file >> records;

for (int i=0;i<records;i++)
{
    our_struct tmp;

    ....
    file >> tmp.int;
    file >> tmp.float;
    ....
    
    our_vector.add(our_struct);


}

Как-то так.

crutch_master ★★★★★
()

А всё оттого что некии умники развивая бинарный формат (которому кстати лет больше 10), не просто добавили новых полей в запись, но одно поле в начале каждой записи сделали побольше, а ещё два поменяли местами («так логичнее» блджат). Есть большое подозрение, что на достигнутом они не остановятся, а поддерживать надо всё форматы :(

Вот же олени.

crutch_master ★★★★★
()

чё? тебе для этого


struct PACKED Record {
  uint32_t a;
  uint16_t b;
  uint8_t c;
  uint8_t d;
} record;
..
read(fd, (void *)&record, sizeof(Record));

нужна библиотека на бусте в перемешку с стл? Да ты гонишь.

nanoolinux ★★★★
()
Ответ на: комментарий от panter_dsd

Буфферизация опциональна, но иногда полезна для производительности (зависит от объёмов). Аллокаторы не нужны. А вот с reinterpret_cast вон из профессии - во-первых, нет никаких гарантий на выравнивание, во-вторых, endianess. Поэтому нужно читать в байтовый буффер, потом заполнять из него структуру строя широкие поля из отдельных байтов.

Готового фреймворка для этого я не знаю, поэтому как раз пишу свой.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

А вот с reinterpret_cast вон из профессии - во-первых, нет никаких гарантий на выравнивание, во-вторых, endianess.

А вот и сферический программист в вакууме.

nanoolinux ★★★★
()

IMNSHO, тут как раз паттерн для фабрики. Вопрос будешь ты делать это на си или си++, соотно фабрика должна вернуть либо пару указателей на функции чтения-записи формата, либо объект, этим занимающийся.

pef-secure
()
Ответ на: комментарий от slovazap

А вот с reinterpret_cast вон из профессии

Ну, т.е. тот, кто придумал этот элемент языка, должен был пойти работать дворником? Как же ж так вышло, что при создании языка забыли видного специалиста спросить, как slovazap? Непорядок!

pef-secure
()

очевидно придётся софтинку переделывать с любимого C на С++
поддерживать надо всё форматы

Как это связано, интересно?

В сложных случаях, если макросами или функциями получается плохо, можно генерировать сериализатор/десериализатор пакетов

anonymous
()
Ответ на: комментарий от nanoolinux

чё? тебе для этого...

мне для того, что потом из этого получается, чтобы одноообразно читать транспортные форматы от разных версий и конверсить их в рабочую структуру/объект

struct PACKED Record_v1 {
  uint32_t a;
  uint16_t b;
  uint8_t c;
  uint8_t d;
};
struct PACKED Record_v2 {
  uint32_t a;
  uint16_t b;
  uint16_t c; //<- например тут байтик добавили
  uint8_t d;
};
struct PACKED Record_v3 {
  // то-же чуть другой формат
};
MKuznetsov ★★★★★
() автор топика
Ответ на: комментарий от panter_dsd

Порядок байт легко конвертируется, поэтому проблем не вижу.

Я назвал две причины почему это не работает, а не одну.

Ну, т.е. тот, кто придумал этот элемент языка, должен был пойти работать дворником?

Нет.

slovazap ★★★★★
()
Ответ на: комментарий от panter_dsd

Я повторяю, #pragma pack не даёт никаких гарантий. Более того, это вообще не конструкция языка C/C++.

slovazap ★★★★★
()
Ответ на: комментарий от nanoolinux

>А вот с reinterpret_cast вон из профессии - во-первых, нет никаких гарантий на выравнивание,
А вот и сферический программист в вакууме.

Хрен там, сферические - это как раз вы, те, кто считает, что «весь мир состоит из Intel-PC».

alegz ★★★★
()
Ответ на: комментарий от pef-secure

> А вот с reinterpret_cast вон из профессии
Ну, т.е. тот, кто придумал этот элемент языка, должен был пойти работать дворником?

Не за сам элемент, а за его использование для сериализации структур.

alegz ★★★★
()
Ответ на: комментарий от alegz

Intel-PC

Хаха, я вообще для арма пишу. А начальник сейчас уговаривает для микроблейза чего-то наваять. Так что мимо.

Прикол в том, что хоть с интерпрет, хоть без него ты ничего вменяемого на сплюсе всё равно не напишешь. Такие дела бро.

nanoolinux ★★★★
()
Ответ на: комментарий от MKuznetsov

Вот тебе конвертер на эрланге. За пять с половиной минут можно написать тсп сервер, и повесить на vps. Но это уже другая история.

conv(Bin) ->
  {A,B,C,D} = parce(Bin),
  <<A:32, B:32, C:32, D:32>>.

parce(B) ->
  <<V:1, Rest/binary>> = B, % one byte for version, for example.
  case V of
    0 -> parce(v1, Rest);
    1 -> parce(v2, Rest);
    2 -> parce(v3, Rest)
  end.

parce(v1, <<A:32, B:16, C:8, D:8>>) -> {A,B,C,D};
parce(v2, <<A:32, B:16, C:16, D:8>>) -> {A,B,C,D};
parce(v3, <<A:32, B:16, C:16, D:16>>) -> {A,B,C,D}.

nanoolinux ★★★★
()
Последнее исправление: nanoolinux (всего исправлений: 1)
Ответ на: комментарий от nanoolinux

Прикол в том, что хоть с интерпрет, хоть без него ты ничего вменяемого на сплюсе всё равно не напишешь

Без reinterpret будет

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

типа забираешь из буфера следующий кусок по схеме (с учётом версии в т.ч.), делаешь ntoh* в поле числа если нужно и т.д.

http://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats

motto
()
Ответ на: комментарий от MKuznetsov
struct PACKED Record {
  uint32_t a;
  uint16_t b;
  uint8_t c;
  uint8_t d;
} record;

struct PACKED Record_v1 {
  uint32_t a;
  uint16_t b;
  uint8_t c;
  uint8_t d;
};
struct PACKED Record_v2 {
  uint32_t a;
  uint16_t b;
  uint16_t c; //<- например тут байтик добавили
  uint8_t d;
};
struct PACKED Record_v3 {
  // то-же чуть другой формат
};

inline template<class T> int my_read(T& x){
      return read(fd, (void *)x, sizeof(T));
}

так?

next_time ★★★★★
()
Ответ на: комментарий от next_time

Не (void *)x, а &x.

И не так:

#include <cstdint>
#include <algorithm>

struct Record_v1 {
  uint32_t a;
  uint16_t b;
  uint8_t c;
  uint8_t d;
};

struct Record_v2 {
  uint32_t a;
  uint16_t b;
  uint16_t c; //<- например тут байтик добавили
  uint8_t d;
};

int main() {
    {
        static char buf[256];
        Record_v1 x = {1, 2, 3, 4};
        std::copy((char*)&x, (char*)&x + sizeof(x), buf);
        Record_v2 *y = (Record_v2*)buf;
        printf("a = %d, b = %d, c = %d, d = %d\n", y->a, y->b, y->c, y->d);
        // a = 1, b = 2, c = 1027, d = 0
    }
    {
        static char buf[256];
        Record_v2 x = {1, 2, 3, 4};
        std::copy((char*)&x, (char*)&x + sizeof(x), buf);
        Record_v1 *y = (Record_v1*)buf;
        printf("a = %d, b = %d, c = %d, d = %d\n", y->a, y->b, y->c, y->d);
        // a = 1, b = 2, c = 3, d = 0
    }
}

Максимум на данной машинке можно сделать write данной структуре, чтобы потом сделать обратно read в неё же — выравнивание, порядок байт, более сложная сериализация и версионинг с конвертациями потребуют таки писать нормально.

motto
()
Ответ на: комментарий от motto

что не так?

выравнивание, порядок байт

ничем не помешают.

более сложная сериализация и версионинг с конвертациями

и это тоже

next_time ★★★★★
()
Ответ на: комментарий от motto

алсо

более сложная сериализация

и - мелкий фиксированный заголовок (id. формата, № версии...)

- заголовок чей формат возможно будет зависить от версии

- далее подряд без промежутков идут записи фиксированного размера, формат зависит от версии

== /0

next_time ★★★★★
()
Ответ на: комментарий от next_time

Прочитаешь версию из заголовка и сделаешь switch с my_read(то), my_read(сё) во вариантах? Можно, только всё равно переносимость нужно учитывать.

motto
()
Ответ на: комментарий от motto

Прочитаешь версию из заголовка и сделаешь switch с my_read(то), my_read(сё) во вариантах?

примерно так, только в случае плюсов, там вместо свитч будут виртуальные функции.

next_time ★★★★★
()
Ответ на: комментарий от crutch_master

Не знаешь же причин. Вполне возможно размерности перестало хватать. А раз пришлось ломать заодно и пофиксили старый косяк.

anonymous
()
Ответ на: комментарий от motto

только всё равно переносимость

обычно переносимость между аппаратными платформами (кроме arm <-> 86) штука сомнительной нужности из-за специфики применения аппаратной части.

next_time ★★★★★
()
Ответ на: комментарий от anonymous

А раз пришлось ломать заодно и пофиксили старый косяк.

И сломали совместимость.

crutch_master ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.