Может ли str_replace безопасно использоваться в кодированной кодировке UTF-8, если в качестве аргументов она содержит только заданные строки с кодировкой UTF-8? - программирование

Может ли str_replace безопасно использоваться в кодированной кодировке UTF-8, если в качестве аргументов она содержит только заданные строки с кодировкой UTF-8?

PHP str_replace() предназначался только для строк ANSI и, как таковой, мог искажать строки UTF-8. Однако, учитывая, что он двоично-безопасный, будет ли он работать правильно, если в качестве аргументов были заданы только строки UTF-8?

Изменить: я не ищу функцию замены, я просто хотел бы знать, правильна ли эта гипотеза.

4b9b3361

Ответ 1

Да. UTF-8 преднамеренно спроектирован таким образом, чтобы эта и другая аналогичная обработка, не поддерживающая Unicode.

В UTF-8 любая последовательность байтов, отличных от ASCII, представляющая действительный символ, всегда начинается с байта в диапазоне \xC0-\xFF. Этот байт не может появляться нигде в последовательности, поэтому вы не можете сделать действительную последовательность UTF-8, которая соответствует части символа.

Это не относится к старым многобайтовым кодировкам, где разные части байтовой последовательности неразличимы. Это вызвало множество проблем, например, попытку заменить обратную косую ASCII в строке Shift-JIS (где byte \x5C может быть вторым байтом символьной последовательности, представляющей что-то еще).

Ответ 2

Правильно, потому что многобайтовые символы UTF-8 являются исключительно символами не-ASCII (128+ байтов), начинающимися с байта, который определяет, сколько байтов следует, поэтому вы не можете случайно попасть в одну часть UTF-8 многобайтовый символ с другим.

Чтобы визуализировать (абстрактно):

  • a для символа ASCII
  • 2x для 2-байтового символа
  • 3xx для 3-байтового символа
  • 4xxx для 4-байтового символа

Если вы соответствуете, скажем, a2x3xx (a bytes в диапазоне ASCII), так как a < x и 2x не могут быть подмножеством 3xx или 4xxx, и так далее, вы можете быть уверены, что ваш UTF-8 будет правильно соответствовать, учитывая предпосылки, что все строки определенно действительны UTF-8.

Изменить: см. bobince ответ для менее абстрактного объяснения.

Ответ 3

Ну, у меня есть встречный пример: у меня есть UTF8-кодированные настройки ".ini", в котором указаны параметры приложения, такие как имя отправителя электронной почты. В нем написано что-то вроде:

email_from = Märta

и я прочитал его оттуда до переменной $sender. Теперь, когда я снова заменю тело сообщения (UTF8)

С уважением {} Отправитель

$message = str_replace("{sender}",$sender_name,$message);

Письмо абсолютно верно во всех отношениях, но отправитель полностью сломан. Существуют и другие случаи (например, explode()), когда что-то происходит с строкой UTF. Это здорово до конверсии, но не после него. Извините, что, похоже, нет способа исправить это поведение.

Изменить. На самом деле, explode() участвует в разборе файла .ini, поэтому проблема может быть в самой этой функции, поэтому str_replace() может быть невиновным.

Ответ 4

Да, я думаю, это правильно, по крайней мере, я не нашел встречного примера.

Ответ 5

Нет, ты не можешь. Из практики я говорю вам, если у вас есть несколько многобайтовых символов, таких как ◊ и т.д., А другие - не многобайтные, это не будет работать правильно, потому что есть символы, которые занимают 2-4 места, str_replace принимает фиксированные байты и заменяет... В результате у нас есть что-то, что не является символом мусора и т.д.