2

ファイルに基づくオブジェクトを使用して、string 値と int 値を読み書きしていQSettingsます。後で別のプロセスから値を読み取ろうとすると、値は int ではなく文字列として読み取られます。

これは、値を書き込むために使用しているコードです。

QSettings settings("TestQSettings.ini", QSettings::IniFormat);
settings.setValue("AAA",QString("111"));
settings.setValue("BBB",222);

作成されるファイルは次のとおりです。

[General]
AAA=111
BBB=222

これは、値を読み取るために使用しているコードです。

QVariant qvar = settings.value("AAA");
std::cout << "AAA type " << qvar.type() << std::endl;
qvar = settings.value("BBB");
std::cout << "BBB type " << qvar.type() << std::endl;

同じプロセスからこのコードを実行すると:

AAA type 10
BBB type 2

このコードを別のプロセスから実行すると:

AAA type 10
BBB type 10

読み取った後に型を変換できることはわかっています。残念ながら、この解決策では Windows の従来のクロスプラットフォーム コードを変更する必要がありますが、これは変更したくありません。たとえば、RegQueryValueEx().

文字列と整数の型情報を保存して読み取ることはできますか?

たとえば、文字列には引用符が""あり、整数にはありません。

[General]
AAA="111"
BBB=222

この問題は、Linux 上の Qt 4 と Qt 5 の両方に存在します。

4

3 に答える 3

1

クライアントが何を期待しているのかを知らずに、任意のタイプのバリアントを保存および復元する必要があるコンポーネントについて、この問題を解決しました。typeName()解決策は、バリアントを各値と一緒に保存することでした。

void store(QSettings& settings, const QString& key, const QVariant& value)
{
    settings.setValue(key+"value", value);
    settings.setValue(key+"type", value.typeName());
}

読み返すときは、型名とconvert()、まだ正しい型でない場合はバリアントも読み込んでから返します。

QVariant retrieve(const QSettings& settings, const QString& key)
{
    auto value = settings.value(key+"value");
    const auto typeName = settings.value(key+"type").toString();

    const bool wasNull = value.isNull();                         // NOTE 1
    const auto t = QMetaType::type(typeName.toUtf8());           // NOTE 2

    if (value.userType() != t && !value.convert(t) && !wasNull) {
        // restore value that was cleared by the failed convert()
        value = settings.value(key+"value");
        qWarning() << "Failed to convert value" << value << "to" << typeName;
    }

    return value;
}

ノート

  1. 変数がそこにあるのwasNullは、次のようなわずかな問題があるためですconvert()

    警告:歴史的な理由から、null を変換するQVariantと、必要な型の null 値 (たとえば、 の空の文字列QString) とfalse.

    この場合、誤解を招くような戻り値を無視し、正常に変換された正しい型の null バリアントを保持する必要があります。


  1. UTF-8 が名前の正しいエンコーディングであるかどうかは明らかではありませQMetaTypeん (おそらくローカル 8 ビットが想定されていますか?)。私のタイプはすべてASCIIなので、toLatin1()代わりに使用するだけで、より高速になる可能性があります。それが問題である場合は、(暗黙的な変換の代わりに) メソッドで使用QString::fromLatin1して、クリーンな往復を保証します。store()char*QString

    型名が見つからない場合は;tになります。QMetaType::UnknownTypeそれconvert()は失敗し、変換されていないバリアント (または null) を返すため、問題ありません。たいしたことではありませんが、通常の使用では発生しないまれなケースであり、システムはかなり迅速に回復します。

于 2016-08-25T14:36:24.830 に答える
1

おっと、.ini ファイルまたはレジストリを使用していますか?

.ini ファイルでは、すべて文字列であるため、タイプが何であったかを知ることは明らかに不可能です。バリアントの整数への変換を試みることができ ( !は使用しないでcanConvertください)、変換された場合は整数であると想定します。

レジストリを使用QSettingsすると、期待どおりに機能します。

何が問題なのか本当にわかりません。.ini型情報を保持したい場合は、ファイルを使用しないでください。プラットフォームに依存する方法でコードを手動で記述した場合、まったく同じ問題に直面するでしょう。

引用符で囲まれた文字列をファイルに明示的に書き込み.ini、それらを読み戻すときに引用符の存在を確認できます。引用符が存在しない場合は、整数への変換を試すことができます。

于 2013-10-14T11:29:12.123 に答える
0

解決策は非常に単純であることがわかりました。

値が INI ファイルに書き込まれると、型が認識されます。SetValue の直前に値 "\"STRING を追加しています

値が INI ファイルから読み戻されるとき。文字列型に上記の接尾辞があることを確認します。もしそうなら、私は接尾辞を切り落とします。そうでない場合は、文字列ではなく整数であると想定します。

魔法のように動作します!

皆さん、特に @Kuba Ober が実際にソリューションを配布してくれてありがとう。

于 2013-10-15T06:09:54.997 に答える