首页 > 解决方案 > 从 lineEdit QT 获取 unicode 并将其写入文件

问题描述

我有一个有lineEdit对象的代码。该对象以任何语言(无法选择哪种语言)进入它,因此它必须支持 Unicode。然后我必须将 Unicode 从中取出并将其写入文件。

我的问题是,lineEdit将文本转换为纯 ASCII 并在我得到它之前将其放入QSring,所以我一次又一次地收到垃圾邮件。

这是我正在尝试做的示例代码:

bool MainWindow::write_file(QString path, QString data)
{
    QFile file( path );
    if (file.open(QIODevice::WriteOnly))
    {
        QTextStream stream( &file );
        stream << data.toUtf8() << endl; // tried this -> didn't work...
        stream << data << endl;
    }else

    {
        return false;
    }

    file.close();
    return true;
}

void MainWindow::on_pushButton_clicked()
{
    // ui->lineEdit->text bring to me the unicode into QString allready
    // how can encode the data to utf-8 BEFORE it get into QString?
    write_file(PYTHON_DB_COMMAND, ui->lineEdit->text());
}

标签: c++qt

解决方案


你把东西混在一起了。

Qt 绝对支持 Unicode;QLineEdit::text()返回 a QString,它是 UTF-16 代码单元的序列。你错的是后面的 IO 部分;特别是,您在滥用QTextStream.

让我们把它放在一边。在这里写下 UTF-8 内容的简单方法就是打开QFile并直接写入转换为 UTF-8 的字符串。

QFile file(path);
if (file.open(QIODevice::WriteOnly)) {
    file.write(data.toUtf8());
    file.putchar('\n');
}

StraightQFile仅适用于字节序列,我们放入其中的内容会写入文件中(文本模式下的白痴换行翻译除外,但我离题了);data.toUtf8()返回从 UTF-16 转换为 UTF-8 的字符串,并将其写入文件而不用大惊小怪。

那有什么关系QTextStream呢?好吧,QTextStream的工作是提供帮助以将类似文本的内容写入文件(在某种程度上,QTextStreamQIODevice什么std::ostreamstd::streambuf1);因此,它提供了轻松输出QString值的方法。

但是,QString它是由 UTF-16 代码单元组成的,而底层文件是面向字节的,因此需要进行转换。为此,QTextStream使用一个 internal QTextCodec,如果没有显式设置 using setCodec则 isQTextCodec::codecFromLocale(),在 Windows 系统上通常是一些遗留编码(例如 windows-1252),无法表示大部分 Unicode;因此输出中的问号。

即使显式使用QString::toUtf8()并在其上写入结果QTextStream也无济于事:由于它是为编写text量身定制的,因此它假定QByteArray您传入的是 UTF-8 数据,因此QString使用它的fromUtf8方法将其转换为 a ,然后将其写入(所以,它使用上述编解码器进行转换)。

因此,如果您想QString使用 UTF-8 将数据写入文件,正确的方法QTextStream是首先将其编解码器设置为 UTF-8,然后直接输出您QString的 s:

QFile file(path);
if (file.open(QIODevice::WriteOnly)) {
    QTextStream stream( &file );
    stream.setCodec("UTF-8");
    stream << data << endl;
}

顺便

  • 通常不需要使用endl- 除了输出换行符之外,它还会强制文件刷新,这通常不是您真正需要的(如果输出多行,可能会降低写入性能);
  • 您不需要显式调用close()a QFile- 它会在销毁时自动关闭(因此,在这种情况下,在您的方法结束时)。

笔记

  1. 不幸的是,这并不完全正确;std::streambuf是一个三头怪物,因为它包装了“关联字符序列”(=底层流,例如 OS 文件)和“受控字符序列”(=缓冲),QFile与根据std::codecvt语言环境方面进行代码页转换,从而完全混淆了事物的语义(是std::streambuf字节序列还是文本字符序列?)并使实现复杂化。

    像往常一样,iostreams 仍然是如何设计 IO 库的一个很好的参考。


推荐阅读