Подтвердить что ты не робот

Кросс-платформенные строки (и Unicode) в С++

Итак, я наконец вернулся к своей основной задаче - портировал довольно большой проект на С++ из Windows в Mac.

Сразу же я попал в проблему, когда wchar_t - 16 бит в Windows, но 32-бит на Mac. Это проблема, потому что все строки представлены wchar_t, и будут выполняться строковые данные между машинами Windows и Mac (как в виде данных на диске, так и в виде сетевых данных). Из-за того, как он работает, было бы не совсем просто преобразовать строки в какой-то общий формат перед отправкой и получением данных.

В последнее время мы действительно начали поддерживать гораздо больше языков, поэтому мы начинаем работать с множеством данных Unicode (а также с языками справа налево).

Теперь я мог бы объединить несколько идей здесь и вызвать больше проблем для себя, чем нужно, поэтому я задаю этот вопрос. Мы думаем, что сохранение всех наших данных в памяти, как UTF-8, имеет большой смысл. Это решает проблему wchar_t с разными размерами, это означает, что мы можем легко поддерживать несколько языков, а также значительно уменьшать наш объем памяти (у нас есть большая часть - в основном, на английском языке) - но это не похоже на то, что многие люди делают это. Что-то нам не хватает? Там очевидная проблема, с которой вам приходится иметь дело, где длина строки может быть меньше размера памяти, хранящей эти строковые данные.

Или использует UTF-16 лучше? Или мы должны придерживаться wchar_t и писать код для преобразования между wchar_t и, скажем, Unicode в местах, где мы читаем/записываем на диск или в сеть?

Я понимаю, что это опасно близко к запросам мнений - но мы нервничаем, что упускаем из виду что-то очевидное, потому что не похоже, что есть много классов строк Unicode (например) - но все же есть много кода для преобразования в/из Юникода, например, в boost:: locale, iconv, utf-cpp и ICU.

4b9b3361

Ответ 1

Всегда используйте протокол, определенный для байта, когда используется файл или сетевое соединение. Не полагайтесь на то, как компилятор С++ хранит что-либо в памяти. Для текста в Юникоде это означает выбор как кодировки, так и порядка байтов (хорошо, UTF-8 не заботится о порядке байтов). Даже если платформы, которые вы в настоящее время хотите поддерживать, имеют аналогичную архитектуру, вероятно, придет другая популярная платформа с различным поведением или даже новая ОС для одной из ваших существующих платформ, и вы будете рады, что напишете переносимый код.

Ответ 2

Как правило: UTF-16 для обработки, UTF-8 для связи и хранения.

Конечно, любое правило может быть нарушено, и этот камень не высечен. Но вы должны знать, когда это нормально, чтобы сломать его.

Например, может быть хорошей идеей использовать что-то еще, если используемая вами среда хочет чего-то другого. Но API-интерфейсы Mac OS X используют UTF-16, как и Windows. Таким образом, UTF-16 имеет больше смысла. Сложнее преобразовать, прежде чем вы ставите/получаете вещи в сети (потому что вы, вероятно, делаете это в 2-3 процедурах), чем все конверсии для вызова API OS.

Также важно, какой тип приложения вы разрабатываете. Если это что-то с очень маленькой текстовой обработкой и очень мало звонков в систему (что-то вроде сервера электронной почты, который в основном перемещает вещи без их изменения), то UTF-8 может быть хорошим выбором.

Итак, насколько вы можете ненавидеть этот ответ, "это зависит".

Ответ 3

Я использую UTF-8 как внутреннее представление. Вы просто теряете проверку длины строки, и в любом случае это не очень полезно. Для преобразования Windows API я использую свои собственные функции преобразования Win32 которые я придумал здесь. Поскольку Mac и Linux (по большей части, стандартный UTF-8, не нуждаются в том, чтобы конвертировать что-либо там). Бесплатные бонусы:

  • использовать простой старый std::string.
  • байтовый сетевой/потоковый транспорт.
  • Для большинства языков замечательный объем памяти.
  • Для большей функциональности: utf8cpp

Ответ 4

ICU имеет строковый класс С++, UnicodeString