Если вы не собираетесь использовать библиотеку сериализации, я предлагаю добавить поддержку сериализации в каждый класс:
struct My_Struct
{
std::string my_string;
unsigned int my_int;
void Load_From_Buffer(unsigned char const *& p_buffer)
{
my_string = std::string(p_buffer);
p_buffer += my_string.length() + 1; // +1 to account for the terminating nul character.
my_int = *((unsigned int *) p_buffer);
p_buffer += sizeof(my_int);
}
};
unsigned char * const buffer = ReadFile(filename);
unsigned char * p_buffer = buffer;
My_Struct my_variable;
my_variable.Load_From_Buffer(p_buffer);
Некоторые другие полезные методы интерфейса:
unsigned int Size_On_Stream(void) const; // Returns the size the object would occupy in the stream.
void Store_To_Buffer(unsigned char *& p_buffer); // Stores object to buffer, increments pointer.
С помощью шаблонов вы можете расширить функциональность сериализации:
void Load_From_Buffer(std::string& s, unsigned char *& p_buffer)
{
s = std::string((char *)p_buffer);
p_buffer += s.length() + 1;
}
void template<classtype T> Load_From_Buffer(T& object, unsigned char *& p_buffer)
{
object.Load_From_Buffer(p_buffer);
}
Редактировать 1: причина не писать структуру напрямую
В C и C++ размер структуры может не равняться сумме размеров ее элементов.
Компиляторам разрешено вставлять заполнение или неиспользуемые пространство между элементами, чтобы элементы были выровнены по адресу.
Например, 32-разрядный процессор предпочитает получать данные с границами в 4 байта. Наличие одного char
в структуре, за которым следует int
, приведет к тому, что int
будет иметь относительный адрес 1, который не кратен 4. Компилятор дополнит структуру так, чтобы int
выровнялось по относительному адресу 4. .
Структуры могут содержать указатели или элементы, содержащие указатели.
Например, тип std::string
может иметь размер 40, хотя строка может содержать 3 символа или 300. Она содержит указатель на фактический данные.
Endianess.
С многобайтовыми целыми числами некоторые процессоры, такие как старший байт (MSB), также известный как Big Endian, сначала (то, как люди читают числа) или наименее значимый байт, также известный как Little Endian. Для чтения в формате Little Endian требуется меньше схем, чем в формате Big Endian.
Редактировать 2: Варианты записей
При выводе таких вещей, как массивы и контейнеры, вы должны решить, хотите ли вы выводить полный контейнер (включая неиспользуемые слоты) или выводить только элементы в контейнере. Для вывода только элементов в контейнере будет использоваться метод вариантной записи.
Два метода вывода записей вариантов: количество, за которым следуют элементы, или элементы, за которыми следует дозорный. Последнее — это то, как записываются строки в стиле C, где часовой является нулевым символом.
Другой метод заключается в выводе количества элементов, а затем предметов. Итак, если бы у меня было 6 чисел, 0, 1, 2, 3, 4, 5, вывод был бы таким:
6 // Количество элементов
0
1
2
3
4
5
В приведенном выше методе Load_From_Buffer я бы создал временный объект для хранения количества, записал его, а затем проследил за каждым элементом из контейнера.
person
Thomas Matthews
schedule
29.01.2013
struct1.string = *(bytePtr + sizeof(char)*40); struct1.int1 = *(bytePtr + (sizeof(char)*40 + sizeof(int));
. Опять же, остерегайтесь порядка следования байтов, вам гораздо лучше сериализовать свои данные. - person lcs   schedule 30.01.2013currentpointer
в строку, а затем выполнении функции копирования строки, чтобы создать правильную строку для вашего поля строковых данных --- используйте функцию копирования строки фиксированной длины, чтобы она не вечно искала нуль терминатор. - person StarPilot   schedule 30.01.2013boost::serialize
, а также поищите в Интернете сериализацию c++. - person Thomas Matthews   schedule 30.01.2013