У меня есть 3D-том, представленный в виде вектора вектора вектора с плавающей точкой, который я хочу сохранить в двоичном файле. (Это объем плотности, восстановленный по рентгеновским снимкам, полученным с КТ-сканера.)
Теперь я мог бы сделать это следующим образом:
//iterate through the volume
for (int x = 0; x < _xSize; ++x){
for (int y = 0; y < _ySize; ++y){
for (int z = 0; z < _zSize; ++z){
//save one float of data
stream.write((char*)&_volume[x][y][z], sizeof(float));
}
}
}
Это в основном работает. Однако я спрашиваю себя, в какой степени это не зависит от платформы. Я хотел бы создать файл, идентичный независимо от системы, в которой он был создан. Таким образом, могут быть машины под управлением Windows, Linux или Mac, они могут иметь длину слова 32 бит или 64 бит и порядок байтов с прямым или прямым порядком байтов.
Я полагаю, если бы я сделал это так, как это было сделано выше, это было бы не так. Теперь, как я мог этого достичь? Я слышал о сериализации, но я не нашел конкретного решения для этого случая.
Буферы протокола Google: бесплатные, кодируются в двоичный код, доступны на нескольких языках, также работают на большинстве платформ. Для ваших требований я бы серьезно рассмотреть GPB. Будьте осторожны, Google выпустил несколько версий, и они не всегда были обратно совместимы, то есть старые данные не обязательно читаются новыми версиями кода GPB. Я чувствую, что он все еще развивается и будут происходить дальнейшие изменения, что может быть неприятно, если ваш проект будет развиваться в течение многих лет.
ASN.1, дедушка из всех них, очень хороший язык схемы (можно установить ограничения по значению и размеру, что является потрясающим способом избежать переполнения буфера и обеспечивает автоматическую проверку потоков данных при условии правильности автоматически сгенерированного кода), некоторые бесплатные инструменты , увидеть эта страница (в основном, хотя они стоят денег). Язык схем GPB является своего рода плохой имитацией ASN.1.
Я решил проблему с помощью Qt Datastream
учебный класс. Qt в любом случае является частью моего проекта, поэтому дополнительные усилия минимальны. Я могу сказать Datastream
возражать точно, если я хочу сохранить свой floats
использование одинарной (32-битной) или двойной (64-битной) точности, и если я хочу использовать байтовый порядок с прямым или младшим порядком байтов. Этого вполне достаточно для того, что мне нужно; Мне не нужно сериализовать объекты. Файлы, которые я сохраняю, теперь имеют одинаковый формат на всех платформах (по крайней мере, они должны), и это все, что мне нужно. После этого они будут прочитаны сторонними приложениями, которым будет предоставлена эта информация (порядок байтов, точность). Так сказать это не имеет значения точно как мои поплавки спасены, но я знать как они сохраняются и что это не зависит от того, на какой платформе вы запускаете программу.
Вот как теперь выглядит код:
QDataStream out(&file);
out.setFloatingPointPrecision(QDataStream::SinglePrecision);
out.setByteOrder(QDataStream::LittleEndian);
for (int x = 0; x < _xSize; ++x){
for (int y = 0; y < _ySize; ++y){
for (int z = 0; z < _zSize; ++z){
//save one float of data
out<<_volume[x][y][z];
}
}
}
Я удивлен, что нет упоминания о <rpc/xdr.h>
заголовок, для представления внешних данных. Я считаю, что это на всех Unix, и может даже работать на Windows: https://github.com/ralight/oncrpc-windows/blob/master/win32/include/rpc/xdr.h
XDR хранит все примитивные типы данных с прямым порядком байтов и заботится о преобразованиях для вас.