Qtir Qt: имена файлов, отбрасывающие не-Ascii символы
У меня проблемы с QDir, теряющим не-Ascii символы из имен моих файлов.
У меня есть файлы с именами, такими как testingöäüß.txt или exampleΦ.shp, и при попытке использовать утилиты Qt, такие как QDir и QFile, они просто отображаются как 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 просто не справится с этим? Спасибо!
2 ответа
Я знаю, что это старый вопрос, но я столкнулся с той же проблемой. Тот же самый точный код Qt будет хорошо работать на моей виртуальной машине разработки, но когда я перенес его в встроенную систему Linux (работающую на x86, в буквальном смысле на тот же исполняемый файл), в именах моих каталогов просто молча пропали символы, не входящие в ASCII.
Оказалось, QTextCodec::codecForLocale
на моей виртуальной машине dev был установлен UTF-8
и на встроенной коробке это было System
, Если я вручную изменил локаль на UTF-8, прежде чем делать какие-либо операции с файловой системой (вызывая QTextCodec::codecForName("UTF-8")
) все стало работать нормально.
Так почему же это произошло в первую очередь? Я подозреваю, что в процессе уменьшения корневой файловой системы встроенной системы я мог случайно удалить некоторые файлы, относящиеся к локали, которые Qt использовал для автоматического определения локали. Когда он не мог определить, был ли он на UTF-8, он возвращался к Системе, которая по какой-либо причине сломалась (возможно, по той же причине, по которой он не смог обнаружить UTF-8 в первую очередь).
Мне нужно в конечном итоге исправить то, что вызывает автоматическое обнаружение, но в краткосрочной перспективе просто ручная настройка языкового стандарта UTF-8 должна сработать, если у вас возникла такая же проблема.
Обратите внимание, что это не имеет никакого отношения к тому, может ли консоль отображать UTF-8, или как-то связано с ручным преобразованием UTF-16 в UTF-8! Так что ответ Феликса на этот вопрос неверен, по крайней мере, для этой конкретной проблемы. Чтобы полностью исключить возможности консоли из уравнения, я также просто печатал число символов UTF-16 в строке, и каждый не-ASCII-символ фактически делал возвращаемый путь и строки имени файла из QDir::entryInfoList на единицу меньше UTF-16 символ. Кроме того, мертвая распродажа заключается в том, что персонажи были просто раздеты, а не просто заменены мусором или вопросительными знаками или чем-то еще.
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
}
Если вы до сих пор их не видите, это потому, что настройки вашей консоли не позволяют их отображать. Попробуйте записать их в файл или отобразить в графическом интерфейсе - или просто попробуйте открыть файл с таким именем, он будет работать.