Вы путаете различные понятия здесь.
Хранение
Так мы сохраняем / храним / храним наши данные. std::string
- это набор char
с, которые байтов . std::wstring
- это набор wchar_t
s, которые иногда имеют значение в 2 байта (но это не гарантируется!).
Кодирование
Вот что означают данные и как их следует интерпретировать. std::string
, набор байтов, может содержать UTF-8, или UTF-16, или UTF-32, или ASCII, или ShiftJIS, или азбуку Морзе, или JPEG, или фильм, или мою ДНК (счастливая строка !).
В мире существуют сильные соглашения. Например, в Windows принято считать std::wstring
для хранения UTF-16 (потому что для этого удобно двухбайтовое хранилище, а также потому, что так работает Windows API).
Более новые версии C ++ также дают нам такие вещи, как std::u16_string
и std::u32_string
, которые по-прежнему напрямую не имеют никакого понятия о кодировке, но предназначены для использования в UTF-16 и UTF -32 соответственно, потому что их имена делают это намерение более очевидным для читателей кода. В C ++ 20 будет введено std::u8_string
, которое предназначено для обозначения строки в кодировке UTF-8 (в остальном более или менее похоже на std::string
).
Но это всего лишь соглашений . Ничто в типе std::string
не говорит «UTF-8» или что-либо еще. Он не знает, не заботится и не применяет какую-либо кодировку. Он просто хранит байты.
Итак, ваш вопрос о «преобразовании UTF-8 в std::string
» на самом деле не имеет никакого смысла; это все равно что спрашивать, как превратить дорогу в машину.
«Что мне тогда делать?»
Ну, Base64 тоже не кодировка. Ну, на самом деле, это действительно так, но это кодировка поверх кодировки строк. Это способ передачи / экранирования / очистки необработанных байтов, а не способ описания того, как их интерпретировать позже. , запрашивающий cpprest преобразовать из Base64 , это просто преобразует способ предоставления необработанных байтов. Вот почему он дает вам std::vector<char>
, а не std::string
, потому что, хотя (как обсуждалось выше) std::string
не заботится о кодировании, мы иногда используем std::vector<char>
, чтобы действительно, правильно, полностью сказать, что "это У коллекции нет какой-либо конкретной кодировки, поэтому, пожалуйста, не пытайтесь угадать из соглашения или чего-либо еще, что такое кодировка в этом случае использования; все, что она знает, это то, что это набор байтов ". Это зависит от мнения. Некоторые люди все еще будут использовать std::string
для этого; авторы cpprest решили не делать этого.
Суть в том, что использование функции from_base64
не может сказать нам ничего о кодировке текста, который вы получили. Для этого мы должны вернуться к документации для текста. У нас нет доступа к этому, и вы ничего не сказали нам об этом. Если бы это была просто строка JSON, кодировка была бы до библиотеки JSON cpprest, так что вы уже сделали бы. Однако это не так: это что-то, упакованное в представление Base64 тем, кто создал объект JSON. Опять же, эта информация не является чем-то, чем вы поделились с нами.
Но, исходя из выбранных вами имен переменных, данные, которые вы просматриваете , уже имеют формат UTF-8 . Затем вы попытались преобразовать его в UTF-16, что скорее противоположно тому, что вы описали, что вы хотели сделать.
(Аналогично, во втором примере вы взяли a std::wstring
, который [вероятно] уже хранит UTF-16 благодаря L"wide string literal"
, а затем сказали компьютеру, что это UTF-8 и преобразовать его «снова» в UTF-16, а затем извлечь необработанные байты в std::string
. Ничего из этого не имеет смысла.)
Вместо этого, почему бы не буквально просто processXML(utf8_payload);
?
Общие советы
Кодирование может быть довольно сложным, хотя с ним значительно легче справиться, как только вы сосредоточитесь на основных понятиях всех этих уровней абстракции.На будущее и для этого вопроса, если вы хотите уточнить это, вам нужно будет гарантировать, что вы абсолютно чисты на каждом этапе «конвейера» ваших данных, когда они передаются из места A в место B и получаютпреобразованный из типа C в тип D, и что бы то ни было, о том, какая кодировка должна быть на каждом из этих шагов.Если вы хотите изменить кодировку на одном из этих шагов, сделайте это (хотя это должно быть редко!).Но прежде чем писать какой-либо код, убедитесь, что вы точно знаете, что именно вам нужно, в противном случае вы попадете в огромный клубок.
В конце концов вы начнете обнаруживать шаблоны, которые могут помочь, хотя,Например, если вы ожидали некоторого восхитительного вывода не-ASCII и вместо этого увидели странный текст с большим количеством символов "Å" , это, вероятно, UTF-8, который по ошибке интерпретируется как ASCII.Это связано с тем, что специальная последовательность, обозначающая кодовые точки Unicode, большие, чем один байт в UTF-8, часто начинается с байта, числовое значение которого совпадает со значением буквы "Å" в ASCII (хорошо,ИСО / МЭК 8859, но достаточно близко).
Точно так же, если вы получаете японский язык и не ожидаете его, по моему опыту это обычно потому, что вы дали компьютеру несколько байтов и сказали, что они являютсястрока в кодировке UTF-16, когда на самом деле это был UTF-8.Просто вы становитесь более опытными в распознавании этих шаблонов по мере того, как вы больше работаете, и это может помочь вам быстрее исправлять ошибки.
Буквально на прошлой неделе последний пример сэкономил мне немного времени: я сразу понял, чтомои исходные данные должны были быть в формате UTF-8, и поэтому я смог быстро принять решение удалить байт-копию в std::wstring
, который я пытался.Изучение байтов кодирующим способом не выявило паттерна "Å" , и тогда это было так.Это было важно, потому что у меня не было документации для источника данных и, следовательно, я не мог просто посмотреть, какой была кодировка .Я должен был угадать / сделать вывод.Надеюсь, это не будет иметь место для вас здесь.