【问题标题】:Create UTF-8 file in Qt在 Qt 中创建 UTF-8 文件
【发布时间】:2011-01-24 09:39:57
【问题描述】:

我正在尝试在 Qt 中创建一个 UTF-8 编码文件。

#include <QtCore>

int main()
{
    QString unicodeString = "Some Unicode string";
    QFile fileOut("D:\\Temp\\qt_unicode.txt");
    if (!fileOut.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        return -1;
    }

    QTextStream streamFileOut(&fileOut);
    streamFileOut.setCodec("UTF-8");
    streamFileOut << unicodeString;
    streamFileOut.flush();

    fileOut.close();

    return 0;
}

我认为当 QString 默认为 Unicode 并且我将输出流的编解码器设置为 UTF-8 时,我的文件将是 UTF-8。但它不是,它是 ANSI。 我做错了什么?我的琴弦有问题吗?您能更正我的代码以创建 UTF-8 文件吗? 对我来说,下一步是读取 ANSI 文件并将其保存为 UTF-8 文件,因此我必须对每个读取的字符串执行转换,但现在,我想从一个文件开始。 谢谢。

【问题讨论】:

  • 您应该使用 QString::fromUtf8() 将字符串文字转换为字符串。此外,一些编译器在源文件 (MSVC) 中存在非 ascii 编码问题。所以也许也可以尝试在通过例如输入字符串时是否有效。 QInputDialog。我还建议在遇到此类问题时定义 QT_NO_CAST_FROM_ASCII 和 QT_NO_CAST_TO_ASCII 。它会禁用隐式转换,从而更清楚地知道发生了什么。

标签: unicode utf-8 qt4


【解决方案1】:

您的代码绝对正确。唯一让我觉得可疑的部分是:

QString unicodeString = "Some Unicode string";

您确实意识到,您不能只将 Unicode 字符串放在引号中,对吗?默认情况下,QString 使用 Latin1,所以如果它只是重​​音字符,你可能没问题,但最好让你的源代码用 UTF-8 编码并这样做:

QString unicodeString = QString::fromUtf8("Some Unicode string");

这适用于任何可以想象的语言。使用 QObject::trUtf8() 会更好,因为它为您提供了很多 i18n 功能。

编辑

虽然您确实生成了正确的 UTF-8 文件,但如果您希望记事本将您的文件识别为 UTF-8,那就另当别论了。你需要在里面放一个BOM。可以按照另一个答案中的建议完成,也可以通过另一种方式完成:

streamFileOut.setGenerateByteOrderMark(true);

【讨论】:

  • 我不建议将 C++ 源代码保存为 UTF-8 :)
  • @Piotr,为什么? UTF-8(无 BOM)是一种与 US-ASCII 完美兼容并支持任何语言的编码。如果不求助于 QTextStream::setCodecForCStrings() 会导致很多问题,你还能如何在某些母语中使用字符文字?
  • @Sergey。我必须同意 Piotr 的观点。问题是当源文件中确实有非 ASCII 文字时,由预处理器和编译器决定尽量不要破坏它们。我毫不怀疑大多数现代工具都可以处理它。但为什么要碰运气呢?
  • @Ondrej,请注意,某些软件可能不喜欢 BOM,尤其是最初设计时不支持 Unicode。即使没有它,它仍然是有效的 UTF-8,所以是否把它放在那里取决于你。最后,这取决于您计划如何使用生成的文件。
  • BOM 对 UTF-8 文件没有意义,是微软主义。
【解决方案2】:

我通过 QT 创建没有 BOM 的 txt 编码 UTF-8 的经验为:

file.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream out(&file);
out.setCodec("UTF-8"); // ...
vcfline = ctn; //assign some utf-8 characters
out.setGenerateByteOrderMark(false);
out << vcfline; //.....
file.close();

并且文件将编码 UTF-8 而没有 BOM。

【讨论】:

  • 如果从文件中读取,请为输入和输出文件流设置编解码器。
【解决方案3】:

不要忘记UTF-8 编码会将 ASCII 字符编码为一个字节。只有特殊或重音字符才会被编码为更多字节(从 2 到 6 个字节)。

这意味着只要您有 ASCII 字符(unicodeString 就是这种情况),该文件将只包含 8 个字节的字符。因此,您可以向后兼容 ASCII:

UTF-8 可以表示 Unicode 字符集中的每个字符,但与它们不同的是,它具有向后兼容 ASCII 的优点

要检查您的代码是否正常工作,您应该在 unicode 中添加一些重音字符。

我用重音字符测试了你的代码,它运行良好。

如果您想在文件开头添加BOM,可以从添加 BOM 字符 (QChar(QChar::ByteOrderMark)) 开始。

【讨论】:

  • 谢谢 Jerome,您帮助我完成了 BOM。文件确实没问题,但缺少 BOM。我使用 Sergey 的方式将其添加到流中,但非常感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-20
  • 2012-04-21
相关资源
最近更新 更多