LINUX.ORG.RU

Чтение бинарных данных из файла


0

1

День добрый. Есть описание структуры:

typedef struct
{
        DWORD Addr;   //адрес контроллера - источника события
        BS_LOG_EVENT Event;  //идентификатор события
        BS_MOD_STATUS status;    //статус исполнительного устройства
        BYTE source;   //резерв=0
        SYSTEMTIME time;  //время события
        DWORD UserID;  //ID пользователя (для персонализированного события) или 0 - для неперсон.
} BS_LOGDATA;

enum BS_LOG_EVENT {
        BS_EV_NOT_RESPONED  =0x01,              //контроллер не отвечает
        BS_EV_USER_ADD   =0x17,                 //пользователь добавлен
        BS_EV_USER_ADD_FAIL  =0x18,             //ошибка добавления пользователя
        BS_EV_WEIG_SCHED_ERROR    =0x24,        //ошибка временного режима
        BS_EV_WEIG_SCHED_DENIED    =0x25,       //отказ входа по карте согласно временному режиму
        BS_EV_IDENT_WEIG_LOCKED    =0x26,       //отказ входа по карте (сотрудник заблокирован)
        BS_EV_IDENT_WEIG_SUCCESS=0x28,          //идентификация по карте успешна
        BS_EV_IDENT_WEIG_FAILED    =0x27,       //идентификация по карте неудачна
        BS_EV_WEIG_HOL_DENIED    =0x29,         //отказ входа по карте (праздник)
        BS_EV_WEIG_HOL_LOCKED    =0x30,         //праздник заблокирован
        BS_EV_MAGNETIC_CARD_ERROR    =0x31,     //ошибка идентификации по магнитной карте
        BS_EV_MAGNETIC_CARD_SUCCESS    =0x32,   //идентификация по магнитной карте успешна
        BS_EV_MAGNETIC_CARD_FAILED    =0x33,    //идентификация по магнитной карте неудачна
        BS_EV_BAD_FINGER  =0x36,                //отпечаток низкого качества
        BS_EV_IDENT_SUCCESS  =0x37,             //идентификация успешна
        BS_EV_IDENT_FAILED  =0x38,              //идентификация неудачна
        BS_EV_NOT_PASS   =0x39,                 //проход не зафиксирован
        BS_EV_USER_DELETE  =0x47,               //пользователь удален
        BS_EV_USER_DEL_FAIL  =0x48,             //ошибка при удалении пользователя
        BS_EV_USER_LOCK   =0x57,                //пользователь заблокирован
        BS_EV_USER_LOCK_FAIL    =0x58,          //ошибка при блокировки пользователя
        BS_EV_IN1_SIGNALED  =0x64,              //сигнал на вход-1
        BS_EV_USER_UNLOCK  =0x67,               //пользователь разблокирован
        BS_EV_USER_UNLOCK_FAIL    =0x68,        //ошибка разблокировки пользователя
        BS_EV_SYSTEM_START  =0x6A,              //перезапуск системы
        BS_EV_TIME_SCHED_DENIED    =0x6D,       //отказано в доступе (временной режим)
        BS_EV_TIME_SCHED_ERROR    =0x6E,        //ошибка временного режима
        BS_EV_HOLIDAY_DENIED    =0x6F,          //отказано в доступе (праздник)
        BS_EV_IDENT_LOCKED_USER    =0x70,       //отказано в доступе (заблокирован)
        BS_EV_HOL_LOCKED  =0x71,                //отказано в доступе (праздник)
        BS_EV_OPEN_FROM_PC  =0x80,              //открыт с ПК
        BS_EV_CLOSE_FROM_PC  =0x81,             //закрыт с ПК
        BS_EV_USER_ENTER  =0x97,                //вход пользователя
        BS_EV_USER_LEAVE  =0x98,                //выход пользователя
        BS_EV_FTR_IDENT_FAILED    =0x99,        //идентификация по футронику неудачна
        BS_EV_TAMPER_SWITCH  =0xA3,             //корпус вскрыт
        BS_EV_SET_USER_SCHED    =0xB0,          //временной режим назначен
        BS_EV_UNSET_USER_SCHED    =0xB1,        //временной режим отменен
        BS_EV_BUR_NOT_CONNECT    =0xB2,         //ошибка связи с БУР

        BS_EV_TUBUS_NOT_CONNECT    =0xB3,       //СК-24 не подключен
        BS_EV_TUBUS_OPEN  =0xB4,                //тубус взят
        BS_EV_TUBUS_CLOSE  =0xB5,               //тубус возвращен
        BS_EV_TUBUS_OPEN_FAILED    =0xB6,       //тубус не взят
        BS_EV_TUBUS_CLOSE_FAILED=0xB7,          //тубус не возвращен
        BS_EV_TUBUS_ADD   =0xB8,                //тубус добавлен
        BS_EV_TUBUS_REMOVE  =0xB9,              //тубус удален
        BS_EV_SET_USER_TUBUS    =0xBA,          //тубус назначен
        BS_EV_UNSET_USER_TUBUS    =0xBC,        //тубус отменен
        BS_EV_GUARD_OFF   =0xBD,                //защита отключена
        BS_EV_TUBUS_NOTASSIGNED    =0xBE,       //тубус не назначен
        BS_EV_FREE_EXIT_ON  =0xE2,              //режим свободного прохода  включен
        BS_EV_FREE_EXIT_OFF  =0xE3,             //режим свободного прохода выключен
        BS_EV_DOOR_NOTCLOSED    =0xE4,          //дверь не закрыта
        BS_EV_MOD_LOCKED_BY_FINGER    =0xE5,    //модуль заблокирован при попытке взлома по отпечатку
        BS_EV_MOD_LOCKED_BY_CARD    =0xE6,      //модуль заблокирован при попытке взлома по карте
        BS_EV_MOD_UNLOCKED  =0xE7,              //модуль разблокирован
        BS_EV_DOOR_NOTOPENED    =0xE8,          //дверь не открыта
        BS_EV_DOOR_CRASHED  =0xE9,              //взлом двери
        BS_EV_INITIALIZED  =0xF0,               //инициализация
        BS_EV_UNKNOWN                           //неизвестное событие
};

enum BS_MOD_STATUS {
        BS_MOD_STATUS_CLOSE    =0,      //закрыто
        BS_MOD_STATUS_OPEN    =1        //открыто
};

Необходимо написать программу на C++/Python для чтения данных и дальнейшего анализа и обработки. Ввиду нехватки знаний, прошу помощи зала. Приведите примерчик чтения данной структуры из файла. При необходимости могу выслать сам бинарник. Заранее спасибо.

fread (&st, sizeof (BS_LOGDATA), 1, fp);

Просто, но очень платформозависимо

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

Окособочит из-за выравнивания, например.

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

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

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

> какие проблемы с вырвниваем...

Обычные. Тебе не понятно как струтктура в памяти уляжется?

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

Понятно. Мне не понятна, в чем проблема, если все на одной машине одним компилятором

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

> Мне не понятна, в чем проблема, если все на одной машине одним компилятором

ну да, потом добавишь include на «левый» хедер со сторонней кривой библиотеки, а там народные умельцы #pragma pack для своих нужд написали, а (pop) забыли, и новая версия твоей программы радостно похерит все данные у пользователя, или ты свалишь с работы, а новый погромист скажет - а давайте мы другой компилятор возьмем, или дефолтные настройки компилятора поменяем, и будет потом вспоминать тебя и употреблять разные яркие прилагательные

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

Убить за изменение правил Выравнивания POD структур

Вообще плохо это. И постановка задачи тоже плохая. Ответ по уровню постановки задачи

namezys ★★★★ ()

Я бы вам посоветовал следующий подход:
1. объявляем что структура упакована
2. открываем файл и отображаем его в память. (читать через read-ом кусочками размером структуры будет слишком медленно)

Теперь по пунктам: 1. Необходимо выровнять структуру. в GCC это делается через указание атрибута __attribute__((__packed__))

typedef struct
{
        DWORD Addr;   //адрес контроллера - источника события
        BS_LOG_EVENT Event;  //идентификатор события
        BS_MOD_STATUS status;    //статус исполнительного устройства
        BYTE source;   //резерв=0
        SYSTEMTIME time;  //время события
        DWORD UserID;  //ID пользователя (для персонализированного события) или 0 - для неперсон.
} __attribute__((__packed__)) BS_LOGDATA;
в MSVC через #pragma pack (возможно что и GCC тоже схавает такую конструкцию, не пробовал)
#pragma push
#pragma pack(1)
typedef struct
{
        DWORD Addr;   //адрес контроллера - источника события
        BS_LOG_EVENT Event;  //идентификатор события
        BS_MOD_STATUS status;    //статус исполнительного устройства
        BYTE source;   //резерв=0
        SYSTEMTIME time;  //время события
        DWORD UserID;  //ID пользователя (для персонализированного события) или 0 - для неперсон.
} BS_LOGDATA;
#pragma pop
или как то так - гугл в помощь.

2. скелет для mmap:

#include <stdio.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>

int main(int argc, char ** argv)
{
    BS_LOGDATA *buf;
    char *fbuf;
    struct stat file_info;
    int i;

    int fd = open(argv[1],O_RDONLY);

    if (fd == -1 || fstat(fd, &file_info))
    {
	printf("Error: open file\n");
	perror(0);
	return 1;
    };
    
    if (!file_info.st_size)
    {
	close(fd);
	return 0;
    };
    
    if ((fbuf = mmap(0,file_info.st_size,PROT_READ,MAP_SHARED,fd,0)) == MAP_FAILED)
    {
	printf("Error: open file mmap failure\n");
	perror(0);
        close(fd);
	return 1;
    };

    for (i=0;i<file_info.st_size;i+=sizeof(BS_LOGDATA))
      {
	rec=(BS_LOGDATA*)&fbuf[i];
        // тут обработка записи
      };

    munmap(fbuf,file_info.st_size);
    close(fd);
};
PS. а вообще это элементарные вещи, и если они вызывают такие затруднения может сменить работу?

bukaka ()

Самый простой способ - mmap.

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

Самый простой способ - mmap.

А не проще ли поэлементно считывать структуру?

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

а если у тебя не 5 элементов в структуре, а 15?

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

Зачем? Для mmap вам ни read, ни write не придется делать. Имеете доступ к структуре, будто она находится в памяти, а она периодически синхронизируется с диском. Удобно же. И по завершении приложения вам не надо специально конфигурационный файл сохранять - он сохранится «автоматом».

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

Зачем? Для mmap вам ни read, ни write не придется делать.

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

ИМХО у ТС такой уровень знаний, что ему проще сказать, чтоб читал структуру по-элементно.

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

А я и при mmap ни о каких выравниваниях не думаю. Просто делаю себе mmap, и все :)

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

А я и при mmap ни о каких выравниваниях не думаю.

Это как? Предположим у ты пишешь софт под arm. Открыл mmap-ом файл. Как дальше решаешь проблему с выравниванием?

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

Я для ARM не пишу. А в x86 все делается просто:

fd = open(fname, O_RDWR));
buf = mmap(NULL, fsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
И чего тут задумываться о выравнивании? Ядро само все правильно выравнивает...

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от pathfinder

Ну, по крайней мере, безо всяких ухищрений мой способ работает на x86. С другими архитектурами пока не сталкивался...

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