[Interest] QDir::entry(Info)List on macos
Manner Róbert
rmanni at gmail.com
Thu Nov 15 14:54:22 CET 2018
Hi,
((
My local encoding is utf-8, so the source file seems to be the same as well:
> file main.cpp
main.cpp: c program text, UTF-8 Unicode text
))
I think I have found the bug which causes this:
https://bugreports.qt.io/browse/QTBUG-70732
I am currently working on a workaround, I am now able to list the files
now using <dirent.h>:
QStringList results;
DIR *dir;
struct dirent *ent;
QByteArray bpath = path.toUtf8();
if ((dir = opendir (bpath.constData())) != NULL) {
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL) {
results << ent->d_name;
}
closedir (dir);
} else {
/* could not open directory */
perror ("");
}
return results;
This gives back the files successfully, the downside is that they are in
UTF-8 normalization format D (UTF-8-mac) which represents accented
characters like O" format, so the original character (O) + the accent
("). Similarly as "ls -1" does.
And having a QString like that does not match "normal" (==
"normalization format C") UTF-8 strings. Eg.:
QString ch1("\u00D6"); // this is normal representation of "Ö"
QString ch2("O\u0308"); // this specifies O with an accent
qDebug() << ch1 << ch2 << (ch1 == ch2 ? "matches!" : "does not match");
This outputs: "Ö" "Ö" "does not match" not only on mac, but even on linux.
So I also needed to convert "utf8 to utf8" :) for my complete
workaround. Unfortunately I did not find a way to do so with QTextCodec.
(Is there?) So I am trying now iconv... this seems to do the trick, but
quite ugly and inefficient.
QByteArray
utf8_unmac(const QByteArray &utf8_mac)
{
iconv_t conv = iconv_open("UTF-8-mac", "UTF-8");
if (conv == (iconv_t)-1)
{
RAISE(TestRunnerException(QString("Iconv open failed: ") +
sys_errlist[errno]));
}
char *inp = const_cast<char *>(utf8_mac.constData()); // iconv is
moving these thats why the duplication
size_t inp_len = utf8_mac.size();
size_t out_len = inp_len * 2;
QByteArray utf8;
utf8.resize(out_len);
char *out = utf8.data();
if (iconv(conv, &inp, &inp_len, &out, &out_len) == (size_t)-1)
{
RAISE(TestRunnerException(QString("Iconv convert failed: ") +
sys_errlist[errno]));
}
utf8.chop(out_len);
iconv_close(conv);
return utf8;
}
Hope it is useful for someone. To be honest, I always imagined that if
everyone would use UTF-8 life would be much better, now I'm unsure ;)
Br,
Robert
On 11/15/18 9:49 AM, Olivier B. wrote:
> What is the encoding of your source file?
> QString constructors interprets char* as if they are UTF-8. If the
> source file is encoded in your local encoding, the QString created for
> QFile constructor will have a wrong unicode storage of your wanted
> filename, then will try to convert what it thinks is UTF into your
> local encoding to pass the filename to the system calls. Maybe the mac
> explorer can work around this and adjust the displayed name, but the
> Filesystem interface of Qt can't because that puts forbidden
> characters in the real name?
> Le jeu. 15 nov. 2018 à 08:55, Manner Róbert <rmanni at gmail.com> a écrit :
>> On 11/14/18 5:34 PM, Thiago Macieira wrote:
>>> On Wednesday, 14 November 2018 01:34:17 PST Manner Róbert wrote:
>>>> int main() {
>>>> qDebug() << QDir(".").entryList();
>>> QCoreApplication missing. Try again with it.
>>>
>> Tried, without success, still does not display these files. Even tried
>> with QDirIterator, that is also working the same (skipping these files).
>>
>> With further checking I noticed that the files are only not displaying
>> if I do not create them with Qt. Eg I created with "touch filenamé". If
>> I create the same file with QFile, that seems to be found by these dir
>> lists. I know it sounds insane.
>>
>>
>> Locale is utf8:
>>
>>> locale
>> LANG="en_US.UTF-8"
>> LC_COLLATE="en_US.UTF-8"
>> LC_CTYPE="en_US.UTF-8"
>> LC_MESSAGES="en_US.UTF-8"
>> LC_MONETARY="en_US.UTF-8"
>> LC_NUMERIC="en_US.UTF-8"
>> LC_TIME="en_US.UTF-8"
>> LC_ALL="en_US.UTF-8"
>>
>> The modified source code:
>>
>>> cat main.cpp
>> #include <QDirIterator>
>> #include <QDebug>
>> #include <QFileInfoList>
>> #include <QCoreApplication>
>> #include <QFile>
>>
>> int main(int argc, char** argv) {
>> QFile file("éáőú"); // This file is visible in the list! But not any
>> other I create with touch for example.
>> file.open(QFile::WriteOnly);
>> file.close();
>>
>> QCoreApplication app(argc, argv);
>> QDirIterator iterator(".", QDir::Files, QDirIterator::Subdirectories);
>> while (iterator.hasNext())
>> {
>> qDebug() << "QDiriterator" << iterator.next();
>> }
>>
>> qDebug() << QDir(".").entryList(QDir::System | QDir::AllEntries |
>> QDir::Hidden);
>>
>> qDebug() << QDir(".").entryInfoList(QDir::System | QDir::AllEntries |
>> QDir::Hidden);
>> }
>>
>> Thanks in advance for any idea.
>>
>> Robert
>>
>> _______________________________________________
>> Interest mailing list
>> Interest at qt-project.org
>> http://lists.qt-project.org/mailman/listinfo/interest
More information about the Interest
mailing list