Вы путаете вещи.
Qt определенно поддерживает Unicode;QLineEdit::text()
возвращает QString
, который является последовательностью кодовых единиц UTF-16.То, что вы ошибаетесь, это часть ввода / вывода позже;в частности, вы неправильно используете QTextStream
.
Давайте отложим это на мгновение.Простой способ записать содержимое UTF-8 здесь - просто открыть QFile
и записать прямую строку, преобразованную в UTF-8.
QFile file(path);
if (file.open(QIODevice::WriteOnly)) {
file.write(data.toUtf8());
file.putchar('\n');
}
Straight QFile
работает только с байтовыми последовательностями,то, что мы помещаем в нее, записывается в файл (кроме идиотского перевода новой строки в текстовом режиме, но я отвлекся);data.toUtf8()
возвращает вашу строку, преобразованную из UTF-16 в UTF-8, и она записывается в файл без особых хлопот.
Что тогда будет с QTextStream
?Итак, задача QTextStream
состоит в том, чтобы предоставить помощникам возможность записывать текстовое содержимое в файлы (в некотором смысле, QTextStream
означает QIODevice
, что std::ostream
означает std::streambuf
1 );как таковой, он предоставляет методы для простого вывода QString
значений.
Однако QString
состоит из кодовых единиц UTF-16, в то время как базовый файл ориентирован на байты, поэтому необходимо преобразование.Для этого QTextStream
использует внутренний QTextCodec
, который, если явно не задано с помощью setCodec
, равен QTextCodec::codecFromLocale()
, что в системе Windows обычно является устаревшимкодирование (например, windows-1252), неспособное представить большую часть Unicode;отсюда вопросительные знаки в вашем выводе.
Даже если явно использовать QString::toUtf8()
и записать результат на QTextStream
, это не поможет: поскольку он предназначен для записи text , он предполагает, что QByteArray
, который вы передаете,Данные в формате UTF-8, поэтому преобразует их в QString
, используя метод fromUtf8
, а затем записывает их (таким образом, они преобразуются с помощью вышеупомянутого кодека).
Итак, правильный путь, если вы хотите записать QString
данные в файл в UTF-8 с использованием QTextStream
, это сначала установить кодек в UTF-8, а затем прямовыведите QString
s:
QFile file(path);
if (file.open(QIODevice::WriteOnly)) {
QTextStream stream( &file );
stream.setCodec("UTF-8");
stream << data << endl;
}
Кстати
- обычно нет необходимости использовать
endl
- помимо вывода новой строки, это также вызывает сброс файла, который обычноэто не то, что вам действительно нужно (и может снизить производительность записи, если выводится много строк); - вам не нужно явно вызывать
close()
для QFile
- он автоматически закрывается при уничтожении (так что, в этом случае, в конце вашего метода).
Примечания
к сожалению, это не совсем так;std::streambuf
- это трехглавый монстр, поскольку он оборачивает «связанную последовательность символов» (= основной поток, такой как файл ОС) и «контролируемую последовательность символов» (= буферизацию), аналогично QFile
, но он также обрабатывает преобразование кодовой страницы в соответствии с std::codecvt
языковым аспектом, таким образом полностью смешивая семантику объекта (* std::streambuf
последовательность байтов или последовательность текстовых символов?) и усложняя реализацию.
Как обычно, iostreams остается отличной ссылкой на то, как не для разработки библиотеки ввода-вывода.