Может ли str_replace безопасно использоваться в кодированной кодировке UTF-8, если в качестве аргументов она содержит только заданные строки с кодировкой UTF-8?
PHP str_replace()
предназначался только для строк ANSI и, как таковой, мог искажать строки UTF-8. Однако, учитывая, что он двоично-безопасный, будет ли он работать правильно, если в качестве аргументов были заданы только строки UTF-8?
Изменить: я не ищу функцию замены, я просто хотел бы знать, правильна ли эта гипотеза.
Ответы
Ответ 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
принимает фиксированные байты и заменяет... В результате у нас есть что-то, что не является символом мусора и т.д.