Файл Qt UTF-8 в std :: string Добавляет дополнительные символы - PullRequest
0 голосов
/ 11 июля 2019

У меня есть текстовый файл в кодировке UTF-8, в котором есть такие символы, как ², ³, Ç и ó. Когда я читаю файл, используя приведенное ниже, файл, кажется, читается соответствующим образом (по крайней мере, в соответствии с тем, что я вижу в редакторе Visual Studio при просмотре содержимого переменной contents)

QFile file( filePath );
if ( !file.open( QFile::ReadOnly | QFile::Text ) ) {
    return;
}
QString contents;
QTextStream stream( &file );
contents.append( stream.readAll() );
file.close();

Однако, как только содержимое преобразуется в std::string, добавляются дополнительные символы. Например, ² преобразуется в ², когда оно должно быть просто ². Это происходит для каждого не-ANSI символа, добавляется дополнительный Â, что, конечно, означает, что при сохранении нового файла символы не являются правильными в выходном файле.

Я, конечно, пытался просто выполнить toStdString(), я также пытался toUtf8 и даже пытался использовать QTextCodec, но каждый не может дать правильные значения.

Я не понимаю, почему при переходе от файла UTF-8 к QString, а затем к std :: string теряются символы UTF-8. Он должен быть в состоянии воспроизвести точный файл, который был первоначально прочитан, или я что-то упустил полностью?

Ответы [ 2 ]

2 голосов
/ 12 июля 2019

Как отметил в своем ответе Даниэль Камиль Козар, QTextStream не читает в кодировке и, следовательно, на самом деле не читает файл правильно.QTextStream должен установить свой кодек перед чтением файла, чтобы правильно проанализировать символы.Добавил комментарий к приведенному ниже коду, чтобы показать необходимый дополнительный файл.

QFile file( filePath );
if ( !file.open( QFile::ReadOnly | QFile::Text ) ) {
    return;
}
QString contents;
QTextStream stream( &file );
stream.setCodec( QTextCodec::codecForName( "UTF-8" ) ); // This is required.
contents.append( stream.readAll() );
file.close();
0 голосов
/ 12 июля 2019

То, что вы видите, на самом деле является ожидаемым поведением.

Строка ² состоит из байтов C3 82 C2 B2 в кодировке UTF-8.Предполагая, что QTextStream фактически распознает UTF-8 правильно (что не так уж очевидно, , судя по документации , в которой упоминается обнаружение кодировки символов только при наличии спецификации, а вы ничего не сказаличто касается входного файла, имеющего спецификацию), мы можем предположить, что QString, который возвращается QTextStream::readAll, фактически содержит строку ².

QString::toStdString() возвращает кодировку UTF-8вариант строки, которую представляет данный QString, поэтому возвращаемое значение должно содержать те же байты, что и входной файл, а именно C3 82 C2 B2.

Теперь о том, что вы видите вотладчик:

  1. Вы указали в одном из комментариев, что «QString содержит только 0xC2 0xB2 в строке (что правильно).».Это только частично верно: QString использует UTF-16LE внутри, что означает, что его внутренний массив символов содержит два 16-битных значения: 0x00C2 0x00B2.Фактически они сопоставляются с символами Â и ², когда каждый из них кодируется как UTF-16, что доказывает, что QString построен правильно на основе входных данных из файла.Однако ваш отладчик, по-видимому, достаточно умен, чтобы знать, что байты, составляющие QString, кодируются в UTF-16 и, таким образом, правильно отображают символы.
  2. Вы также заявили, что отладчик показываетсодержимое std::string возвращается из QString::toStdString как ².Предполагая, что ваш отладчик использует страшную «кодовую страницу ANSI» для разрешения байтов в символы, когда явно не указано кодирование, и вы используете англоязычную Windows, которая использует Windows-1252 в качестве устаревшей кодовой страницы по умолчанию, все встает на свои места: std::string на самом деле содержит байты C3 82 C2 B2, которые сопоставляются с символами ² в Windows-1252 .

Бесстыдная самостоятельная вилка: I доставленоречь о кодировке символов на конференции в прошлом году.Возможно, его просмотр поможет вам лучше понять некоторые из этих проблем.

И последнее: ANSI не является кодировкой .Это может означать несколько различных кодировок в зависимости от региональных настроек Windows.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...