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

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

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

Ответы [ 5 ]

19 голосов
/ 16 апреля 2010

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

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

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

5 голосов
/ 16 апреля 2010

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

Для визуализации (абстрактно):

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

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

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

1 голос
/ 06 мая 2010

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

email_from = Märta

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

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

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

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

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

0 голосов
/ 29 ноября 2011

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

0 голосов
/ 16 апреля 2010

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

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