2014-11-04 3 views
2

В моей программе пользователь может указать имя файла в командной строке или использовать QFileDialog. В первом случае у меня есть char* без какой-либо информации о кодировании, во второй у меня есть QString.Сохранять символы non-ascii между std :: string и QString

Чтобы сохранить имя файла для последующего использования (последние файлы), мне нужно это как QString. Но чтобы открыть файл с std::ifstream, мне нужен std::string.

Теперь начинается веселье. Я могу сделать:

filename = QString::fromLocal8Bit(argv[1]); 

позже, я могу сделать:

std::string fn = filename.toLocal8Bit().constData(); 

Это работает для большинства персонажей, но не все. Например, слово Раиса будет выглядеть одинаково после прохождения этого преобразования, но на самом деле они имеют разные символы. Итак, пока у меня может быть Раиса.txt, и он отобразит Раиса.txt, он не найдет файл в файловой системе. Большинство писем работает, но и не делает. (Обратите внимание, что он работает правильно, когда файл был выбран в QFileDialog. Это не когда она возникла из командной строки.)

Есть ли лучший способ сохранить имя файла? Прямо сейчас я получаю его в любой родной кодировке и могу проходить в одной кодировке, не зная об этом. По крайней мере, я подумал.

+0

Зачем использовать ifstream для открытия файла вместо QFile? – TheDarkKnight

+1

Файл открывается в другом модуле, который не имеет зависимостей Qt. Он отделен от GUI. – ypnos

+1

Почему вы используете QString :: fromLocal8Bit? Из документации этой функции говорится следующее: «QTextCodec :: codecForLocale() используется для выполнения преобразования из Unicode. Если кодировка локали не может быть определена, эта функция выполняет то же самое, что и дляLatin1().«Похоже, в вашем случае toLatin1(), наконец, вызывается, и когда вы позже вызываете toLocal8Bit(), происходит следующее:« Если эта строка содержит любые символы, которые не могут быть закодированы в локали, возвращаемый массив байтов не определен. Эти символы могут быть подавлены или заменены другим. » –

ответ

1

'и' не является символом ASCII, то есть имеет 8-битовое представление. Как он представлен в argv[1], тогда зависит от ОС. Но он не отображается в одном char.

fromLocal8bit использует то же самое QTextCodec::codecForLocale как toLocal8bit. И как вы говорите, ваш std::string будет содержать «Раиса.txt», так что это не проблема.

В зависимости от того, как ОС определяется std::ifstream хотя std::ifstream может ожидать каждого char быть его собственный char и не пройти через перевод в ОС. Я ожидаю, что вы находитесь в Windows, так как видите эту проблему. В этом случае вы должны использовать std::wstring реализацию std::fstream которое Microsoft конкретны: http://msdn.microsoft.com/en-us/library/4dx08bh4.aspx

Вы можете получить std::wstring от QString с помощью: toStdWString

Смотрите здесь для получения дополнительной информации: fstream::open() Unicode or Non-Ascii characters don't work (with std::ios::out) on Windows

EDIT:

Хороший кросс-платформенный вариант для проектов с доступом к нему: Boost::Filesystem. ypnos Упоминания File-Streams как конкретно уместно.

+0

На самом деле это кросс-платформенный и я тестировал на Linux. Вот почему я воздерживаюсь от wstring прямо сейчас. – ypnos

+1

@ypnos Я не профессионал Linux, но я понимаю что он использует UTF-8 для файловой системы. Поэтому вы можете пойти с '# ifdef', используя' std :: wstring' в Windows и 'QString :: toUtf8' на Linux. Более чистой альтернативой было бы использовать ['Boost: Filesystem'] (http://www.boost.org/doc/libs/1_47_0/libs/filesystem/v3/doc/v3.html). Но я понимаю, что уклоняться от этого , –

+0

Это хорошее предложение. В Linux вы в основном получаете UTF8 в настоящее время, но только в основном. И тогда есть также OS X. Boost: Файловая система - хорошая идея. Из вашего предложения я нашел http://www.boost.org/doc/libs/1_47_0/libs/filesystem/v3/doc/reference.html#File-streams – ypnos

Смежные вопросы