2013-02-16 2 views
2

У меня есть массив байтов данных, который должен быть последовательной кросс-платформенной. Предположим, у меня есть указатель, unsigned char* data, который указывает на какое-то место внутри моего массива, и я хочу читать 4 байта в переменную. Я думаю, что я мог бы просто так:Обработка верификации при чтении из массива байтов в C?

uint32_t my_int = *data; 

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

uint32_t my_int = (data[0] << 3) + (data[1] << 2) + (data[2] << 1) + data[3]; 

Кроме того, я должен сделать те же проверки при написании этих данных с fwrite? Например, если бы я написал, что одни и те же данные в файл с этим кодом:

fwrite(&my_int, sizeof(my_int), 1, fh); 

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

+0

_Byte_ массивы не имеют никакой энтузиазма ... – vonbrand

+0

@vonbrand Ну, очевидно, конечно, они этого не делают, но вопрос в том, будут ли операции * с * этим массивом затронуты консистенцией платформы. –

+0

Что вы пытаетесь сделать? Если это просто массив байтов, endianess не будет проблемой. Вы пытаетесь читать 4 байта как целое число? – tangrs

ответ

3

При чтении или записи двоичных данных вам нужно беспокоиться о endianness. Вам также нужно беспокоиться о переменном размере и, возможно, структуре упаковки, если вы пытаетесь читать/писать целые структуры. Некоторые архитектуры не могут обрабатывать целые числа на границах нечетных переменных, поэтому вы не можете просто захватить целое число непосредственно из двоичного буфера, используя что-то вроде uint32_t myInteger = * (uint32_t *) bufferPtr ++.

Существует множество способов сделать эту работу. В прежние времена, когда скорость и использование ОЗУ были огромными проблемами, мы читали фрагмент данных непосредственно из файла в буфер, а затем при необходимости исправляли континент на месте, используя указатели в структуре.

Вы все еще можете сделать это сегодня, хотя структура упаковки различия между составителями сделать это без проблем, так что он может сделать больше смысла писать некоторые простые I/O процедуры для конкретных типов, таких как

int write_integer_at_position(FILE *, size_t position, uint32_t); 
int read_integer_from_position(FILE *, size_t position, uint32_t *outResult); 
etc 

Те подпрограммы будут заменять байты, если необходимо, возможно, используя htonl, после чтения или перед записью данных на диск. После того, как вы сделали это 20 или 30 раз, вы, вероятно, захотите написать какой-нибудь язык описания данных для сопоставления структур в ОЗУ и файлах. Многие люди это сделали, но я не думаю, что кто-то, в частности, действительно поймал.

1

При использовании целых чисел есть семейство функций/макросов

См

ntol, например

Как упаковки - просто определить протокол и где вещи должны быть размещены. Тогда write мог бы построить массив символов с различными битами в правильных местах. Это должно соответствовать коду, который извлекает эти данные.

1

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

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

Сетевой порядок - это своего рода стандарт де-факто, используемый в протоколах на основе IP. Существуют функции библиотеки, которые могут конвертировать из хоста в сеть и сеть в хост-заказы (см. Ссылку, предоставленную Ed Heal).

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

Может потребоваться также упаковка конструкций, представление типов (целые числа, строки, символы), его размеры и т. Д.