简体   繁体   English

QDataStream有时使用32位浮点数,有时使用40位浮点数

[英]QDataStream uses sometimes 32 bit and sometimes 40 bit floats

I am writing an application that is supposed to write an array of floats to a WAVE file. 我正在编写一个应将浮点数组写入WAVE文件的应用程序。 I am using a QDataStream for this, but this results in a very improbable output that I can't explain. 我为此使用了QDataStream,但这导致了我无法解释的非常不可能的输出。 It seems like the QDataStream sometimes chooses 32 bit floats and sometimes 40 bit floats. 似乎QDataStream有时选择32位浮点数,有时选择40位浮点数。 This messes up the entire output file, since it has to obey a strict format. 由于必须遵守严格的格式,因此会弄乱整个输出文件。

My code roughly looks like this: 我的代码大致如下所示:

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];
    }
}

I can think of no reason of how this code could have such a side-effect. 我想不出该代码如何产生这种副作用的原因。 So I made a minimal example to find out what was going on. 因此,我举了一个最小的例子来了解正在发生的事情。 I replaced the for-loop by this: 我将for循环替换为此:

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

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

Then I opened the output file using Matlab and had a look at the bytes written the file. 然后,我使用Matlab打开了输出文件,并查看了写入文件的字节数。 Those were: 那些是:

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

I chose the values pretty arbitrarily, they just happened to have this effect. 我随意选择了这些值,它们恰好具有这种作用。 Some values are exported as 4-byte and other ones as 5-byte numbers. 一些值导出为4字节,另一些导出为5字节数字。 Does anyone have any idea what may be the cause of this? 有谁知道这可能是什么原因?

Edit: When checking the size of both floats, they do seem to be 4 char s long, though: 编辑:检查两个浮点数的大小时,它们似乎确实长4个char ,但是:

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

The answer lies in the opening of the output file: the QIODevice::Text flag should have been left out, since it is a binary file. 答案在于打开输出文件:由于QIODevice::Text标志是二进制文件,因此应该将其忽略。 If the text-flag is included, a 0d character is inserted before each 0a . 如果包含文本标志,则在每个0a之前插入一个0d字符。 So each float that contains an 0a character seems a char longer because of this. 因此,一个包含每个浮点0a性格似乎char长,因为这一点。

All credits for this answer go to the answers given in: Length of float changes between 32 and 40 bit 此答案的所有功劳均归于以下给出的答案: 浮点长度在32到40位之间变化

Note: I'm not 100% sure I'm right below, and would love to hear I'm wrong, but this is how I think it is: 注意:我不是100%肯定我在下面,并且很想知道我错了,但这就是我的想法:

QDataStream has it's own serialization format, and while I did not check, that is probably related to that. QDataStream有它自己的序列化格式,虽然我没有检查,但可能与此有关。 Point is, it's not meant for what you are trying to do with it: write just any binary format. 重点是,这并不意味着您要尝试使用它:只写任何二进制格式。 You can use the class, but I believe you need to use only writeRawData() method, and take care of byte order etc yourself. 您可以使用该类,但是我相信您只需要使用writeRawData()方法,并自己处理字节顺序等。

I had a similar issue even though I was not using the IODevice::Text flag. 即使我没有使用IODevice :: Text标志,我也遇到类似的问题。 I found that adding a line 我发现添加一行

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

solved the problem to make sure you are in the binary mode. 解决了问题,以确保您处于二进制模式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM