【问题标题】:Qt's QDir: File Names Dropping Non-Ascii CharactersQt 的 QDir:文件名删除非 Ascii 字符
【发布时间】:2016-02-12 22:54:45
【问题描述】:

我遇到了 QDir 从我的文件名中丢失非 Ascii 字符的问题。

我的文件名称如 testingöäüß.txt 或 exampleΦ.shp,当尝试使用 QDir 和 QFile 等 Qt 实用程序时,它们只是显示为 testing.txt 和 example.shp。好像我无法告诉这些类使用哪种编码。我正在尝试 QDirIterator 和 QDir 函数 entryInfoList:

   QDir someDir("/home/blah");  //contains testingöäüß.txt

   QDirIterator dirIter(someDir.absolutePath(), QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files);
   while(dirIter.hasNext())
   {
      QString fileName1 = QFile::decodeName(dirIter.next().toUtf8());
      std::cout << "QDirIterator Name " << fileName1.toStdString().c_str() << std::endl;
   }

   QFileInfoList fileInfoList = someDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files);
   foreach(QFileInfo fileInfo, fileInfoList)
   {
      QString fileName1 = QFile::decodeName(fileInfo.fileName().toUtf8());
      std::cout << "entryInfoList Name " << fileName1.toStdString().c_str() << std::endl;

      QString fileName2 = QFile::decodeName(fileInfo.absoluteFilePath().toUtf8());
      std::cout << "entryInfoList Name2 " << fileName2.toStdString().c_str() << std::endl;

      QString fileName3 =  QString::fromUtf8(dirIter.fileInfo().absoluteFilePath().toStdString().c_str());
      std::cout << "entryInfoList Name3 " << fileName3.toStdString().c_str() << std::endl;
   }

这些打印中的每一个都将缺少非 ascii 字符。似乎一旦您尝试获取要循环的文件名,它们将仅是 ascii。有人对此有任何想法吗?或者 Qt 不能处理这个?谢谢!

【问题讨论】:

  • 尝试删除所有对toUtf8()toStdString()QFile::decodeName() 等的调用。Qt 的默认 UTF-16 编码应该足够了。我也不会依赖 std::cout 能够正确显示非 ascii 字符,因为这将取决于您的控制台设置。

标签: qt unicode qfile qdir qfileinfo


【解决方案1】:

我知道这是一个老问题,但我遇到了同样的问题。完全相同的 Qt 代码在我的开发 VM 上可以正常工作,但是当我将它转移到嵌入式 Linux 系统(在 x86 上运行,所以实际上是相同的可执行文件)时,我的目录名称只是默默地删除了它们的非 ASCII 字符。

原来我的开发虚拟机上的QTextCodec::codecForLocale 设置为UTF-8,而在嵌入式机器上它是System。如果我在执行任何文件系统操作之前手动将语言环境更改为 UTF-8(通过调用 QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"))),一切都会开始正常工作。

那么为什么会发生这种情况呢?我的怀疑是,在精简嵌入式系统的根文件系统的过程中,我可能不小心删除了 Qt 用来尝试自动检测语言环境的一些与语言环境相关的文件。当它无法确定它使用 UTF-8 时,它会退回到 System,无论出于何种原因,它都已损坏(可能出于同样的原因,它一开始就无法检测到 UTF-8)。

我最终需要修复导致它无法自动检测的任何问题,但在短期内,如果您遇到同样的问题,只需手动设置 UTF-8 语言环境即可。

请注意,这与控制台是否可以显示UTF-8无关,也与手动将UTF-16转换为UTF-8有关!所以Felix对这个问题的回答是不正确,至少对于这个特定问题。为了从等式中完全删除控制台的功能,我还简单地打印了字符串中 UTF-16 字符的数量,并且每个非 ASCII 字符实际上使 QDir::entryInfoList 返回的路径和文件名字符串少了一个UTF-16 字符。此外,致命的赠品是字符被简单地删除了,而不仅仅是用垃圾或问号或其他东西代替。

【讨论】:

  • 这个答案已经很老了,但我偶然发现了这个,它似乎解决了我完全相同的问题。我只是想注意这个调用设置了编解码器:QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"))。这里的文档很短,您知道设置“名称编码”是否有任何副作用或影响其他任何地方?不幸的是,它的名称和文档并不能告诉您太多信息。
  • 谢谢,修复了有问题的代码 sn-p。这可能会在使用默认语言环境中的 QTextCodec 读取或输出文本的任何地方产生“副作用”。显然,这是在与文件系统交互时完成的,但我很确定还有其他地方。但是,如果您将所有原始文本都视为 UTF-8,那么您可能无论如何都想要这种副作用。只要实际上没有非 ASCII 字符,UTF-8 就与 ASCII 相同。
  • 谢谢,有同样的想法,但想听听别人的意见:-)
【解决方案2】:

Qt 可以处理带有特殊字符的文件名。你只是让它们在那个字符串转换的东西中消失。 (这完全没有必要)试试这种方式:

#include <QDebug>
//...
QFileInfoList fileInfoList = someDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files);
foreach(QFileInfo fileInfo, fileInfoList)
{
    qDebug() << fileInfo.fileName();//uses qdebug
    std::cout << fileInfo.fileName().toStdWString() << std::endl;//uses a 16Bit string on normal cout
}

如果您仍然看不到它们,那是因为您的控制台设置不允许显示它们。尝试将它们写入文件或在 gui 中显示它们 - 或者只是尝试打开具有该名称的文件,它会起作用。

【讨论】:

  • 那里也没有运气。我可以通过简单地将 testingöäüß 打印到 cout 或 qDebug 来显示外来字符。但是在文件名中找到那些并没有发生。我什至可以这样做: QFile file("/home/blah/testingöäüß.txt"); if(file.exists()) { std::cout
  • 这很奇怪 - 它对我有用 - UNICODE 是为你定义的吗?
猜你喜欢
  • 1970-01-01
  • 2013-09-02
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
  • 2012-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多