QDataStream использует иногда 32-битные, а иногда 40-битные числа с плавающей точкой

Я пишу приложение, которое должно записать массив с плавающей точкой в ​​файл WAVE. Я использую QDataStream для этого, но это приводит к очень невероятному выводу, который я не могу объяснить. Кажется, что QDataStream иногда выбирает 32-битные и иногда 40-битные. Это портит весь выходной файл, поскольку он должен соответствовать строгому формату.

Мой код выглядит примерно так:

float* array;
unsigned int nSamples;

void saveWAV(const QString& fileName) const
{
QFile outFile(fileName);
if (outFile.open(QIODevice::WriteOnly | QIODevice::Text))
{
QDataStream dataStream(&outFile);
dataStream.setByteOrder(QDataStream::LittleEndian);
dataStream.setFloatingPointPrecision(QDataStream::SinglePrecision);

// ... do all the WAV file header stuff ...

for(int ii = 0; ii < nSamples; ++ii)
dataStream << array[ii];
}
}

Я не могу придумать причину, почему этот код может иметь такой побочный эффект. Поэтому я сделал минимальный пример, чтобы узнать, что происходит. Я заменил цикл for следующим образом:

float temp1 = 1.63006e-33f;
float temp2 = 1.55949e-32f;

dataStream << temp1;
dataStream << temp1;
dataStream << temp2;
dataStream << temp1;
dataStream << temp2;

Затем я открыл выходной файл с помощью Matlab и посмотрел на байты, записанные в файле. Это были:

8b 6b 07 09      // this is indeed 1.63006e-33f (notice it's Little Endian)
8b 6b 07 09
5b f2 a1 0d 0a    // I don't know what this is but it's a byte to long
8b 6b 07 09
5b f2 a1 0d 0a

Я выбрал значения довольно произвольно, они просто имели такой эффект. Некоторые значения экспортируются как 4-байтовые, а другие — как 5-байтовые числа. У кого-нибудь есть идеи, что может быть причиной этого?

Редактировать:
При проверке размеров обоих поплавков они кажутся равными 4 charс долго, хотя:

    qDebug() << sizeof(temp1); // prints '4'
qDebug() << sizeof(temp2); // prints '4'

1

Решение

Ответ заключается в открытии выходного файла: QIODevice::Text Флаг должен быть опущен, так как это двоичный файл. Если текстовый флаг включен, 0d символ вставляется перед каждым 0a, Таким образом, каждый поплавок, который содержит 0a персонаж кажется char дольше из-за этого.

Все кредиты за этот ответ идут на ответы, приведенные в:
Длина плавания изменяется от 32 до 40 бит

5

Другие решения

Примечание: я не уверен на 100%, что я прямо ниже, и хотел бы услышать, что я не прав, но я так думаю:

QDataStream имеет свой собственный формат сериализации, и хотя я не проверял, это, вероятно, связано с этим. Дело в том, что оно не предназначено для того, что вы пытаетесь с ним сделать: пишите просто любой двоичный формат. Вы можете использовать класс, но я считаю, что вам нужно использовать только writeRawData() метод, и сами позаботьтесь о порядке следования байтов.

1

У меня была похожая проблема, хотя я не использовал флаг IODevice :: Text. Я обнаружил, что добавление строки

dataStream.device()->setTextModeEnabled(false);

решил проблему, чтобы убедиться, что вы находитесь в двоичном режиме.

1
По вопросам рекламы [email protected]