QSettings and float numeric type do not play nice together
-
I am attempting to read and write float values from/to a text file. Using C++.
The data type within the software is defined as: 'typedef float Float32_t;' I inherited this and
it is not changeable.Results in the text file look like this: "@QVariant(\0\0\0\x87=\xcc\xcc\xcd", which is not acceptable.
Here is the 'write' method:
void writeCustom(const QString &Key, const Float32_t &val)
{
QSettings settings(mFilePath, QSettings::IniFormat);
settings.setValue(Key, QVariant(static_cast<float>(val)));
}This same approach works for double types.
Please weigh in. Thanks -
I am attempting to read and write float values from/to a text file. Using C++.
The data type within the software is defined as: 'typedef float Float32_t;' I inherited this and
it is not changeable.Results in the text file look like this: "@QVariant(\0\0\0\x87=\xcc\xcc\xcd", which is not acceptable.
Here is the 'write' method:
void writeCustom(const QString &Key, const Float32_t &val)
{
QSettings settings(mFilePath, QSettings::IniFormat);
settings.setValue(Key, QVariant(static_cast<float>(val)));
}This same approach works for double types.
Please weigh in. Thanks@wareagle said in QSettings and float numeric type do not play nice together:
Results in the text file look like this: "@QVariant(\0\0\0\x87=\xcc\xcc\xcd", which is not acceptable.
So that I understand. What is "not acceptable"? Assuming that value is correct, and deserializes correctly, that is all
Settingsis supposed to do. Are you saying something like you want to impose requirements on its output (to a file or registry) such that it is human-readable to you? -
Also when double works fine - simply store them as double.
-
Also when double works fine - simply store them as double.
@Christian-Ehrlicher
I agree, but his problem will be that it will deserialize as aQVariant(double)where he presumably requires it to beQVariant(float)? So he may need to do some massaging. -
@Christian-Ehrlicher
I agree, but his problem will be that it will deserialize as aQVariant(double)where he presumably requires it to beQVariant(float)? So he may need to do some massaging.@JonB said in QSettings and float numeric type do not play nice together:
@Christian-Ehrlicher
I agree, but his problem will be that it will deserialize as aQVariant(double)where he presumably requires it to beQVariant(float)? So he may need to do some massaging.I don't understand - QSettings returns a QVariant. QVariant has toFloat()...
And this works fine for me with Qt6.11
double dbl = 1.0; float flt = 1.0f; QSettings settings("D:/tmp.ini", QSettings::IniFormat); settings.setValue("dbl", dbl); settings.setValue("flt", flt);-->
[General] dbl=1 flt=1 -
@JonB said in QSettings and float numeric type do not play nice together:
@Christian-Ehrlicher
I agree, but his problem will be that it will deserialize as aQVariant(double)where he presumably requires it to beQVariant(float)? So he may need to do some massaging.I don't understand - QSettings returns a QVariant. QVariant has toFloat()...
And this works fine for me with Qt6.11
double dbl = 1.0; float flt = 1.0f; QSettings settings("D:/tmp.ini", QSettings::IniFormat); settings.setValue("dbl", dbl); settings.setValue("flt", flt);-->
[General] dbl=1 flt=1@Christian-Ehrlicher
If you havefloat flt = 1.0f; settings.setValue("flt", flt); // stored in a .ini file as flt=1then I don't know where/why the OP comes up with
@QVariant(\0\0\0\x87=\xcc\xcc\xcdin the output/.ini/text file in the first place? Unless by any chance it depends on the value infltrather than a simple1. -
The only real requirement is that the float value must be human readable in order for a user to be able to change it within the file. Like => 0.1234
@wareagle
You're not supposed to do this, but OK :) So please recheck by trying @Christian-Ehrlicher 's example verbatim, where he is showingfloats being stored readably. Try with other values, like whatever your value was, to make sure. If you don't find same result as him please report your Qt version & platform. -
@Christian-Ehrlicher
If you havefloat flt = 1.0f; settings.setValue("flt", flt); // stored in a .ini file as flt=1then I don't know where/why the OP comes up with
@QVariant(\0\0\0\x87=\xcc\xcc\xcdin the output/.ini/text file in the first place? Unless by any chance it depends on the value infltrather than a simple1. -
@JonB The 'starting' value in the text file was 0.1. After reading and then writing it to file it showed the '@Variant..... (I guess binary value, not sure) in the file.
@wareagle
Could you please change @Christian-Ehrlicher 's example to use0.1as the value. Show us the verbatim code and the output. Use0.1for thedoubletoo. Then wait for someone like Christian (not me) to re-test.Please do this before dealing with reading text and converting back, if that is what you do. One thing at a time! Let's see only what the problem writing a float to a
.iniis, standalone. Then, depending, show the shortest possible complete, standalone code demonstrating your issue.If you don't care about this and
doubles do work, don't forget like Christian said you can save as a double and deal with assigning it tofloaton reading. -
@wareagle
Could you please change @Christian-Ehrlicher 's example to use0.1as the value. Show us the verbatim code and the output. Use0.1for thedoubletoo. Then wait for someone like Christian (not me) to re-test.Please do this before dealing with reading text and converting back, if that is what you do. One thing at a time! Let's see only what the problem writing a float to a
.iniis, standalone. Then, depending, show the shortest possible complete, standalone code demonstrating your issue.If you don't care about this and
doubles do work, don't forget like Christian said you can save as a double and deal with assigning it tofloaton reading.@JonB My fall back is doing this processing as a type double, which I already know works. My original question relates to why does float not work? Which no one seems to know. Is this a known issue with QSettings or what? I showed the exact code and the exact output within the file. Qt version 5.2.1. Platform is RHEL 8 Virtual Machine within VMWare.
-
@JonB My fall back is doing this processing as a type double, which I already know works. My original question relates to why does float not work? Which no one seems to know. Is this a known issue with QSettings or what? I showed the exact code and the exact output within the file. Qt version 5.2.1. Platform is RHEL 8 Virtual Machine within VMWare.
@wareagle
You did not show the full code, because although we saw the final output we did not see what thefloatvalue serialized actually was. Which means I cannot repro it. We also saw Christian's complete example, which did work.Qt version 5.2.1.
Are you aware just how old that version is (a decade)? Nobody here will be able to try on that, I suspect? That may be your final answer as to why it does not work, and you may have to use
doubleif that works with that version.At least as of 7 years ago see https://stackoverflow.com/questions/55044655/why-is-qtsettings-storing-floats-in-a-weird-mode-what-am-missing . For your version that is the "answer" --- or someone's best guess at the reason. Sounds like it may have changed in more recent versions.
-
QSettingsis a pretty robust class which has its weaknesses.
IMHO it tries to trade off type safety versus human readability.
If I need waterproof numeric types in settings, never store them directly.
Either I transform them to a string (which is also human readable).
If I need it 100% safe, I use theQDataStream<< and >> operators and store the result in settings as aQByteArray.
That's not human readable, but 100% type safe.Qt version 5.2.1
I think Noah used this version in his shipyard, and it was outdated when he set sails....
How about 6.8 for instance? -
@Axel-Spoerl beat me to it, but quit messing with QVariant, then read/write your INI file as text, since INI is traditionally suppose to be a human readable format in the first place...and use normal stream read/write operations in text mode. This is also important since text mode negates possible issues with endianness of numerical storage.