ord () не работает с utf-8

согласно ISO 8859-1

€ Символ имеет десятичное значение 128

Моя кодировка php-скрипта по умолчанию

echo mb_internal_encoding(); //ISO-8859-1 

Итак, теперь, когда PHP

 echo chr(128); //Output exactly what i want '€' 

Но

 echo ord('€'); //opposite it returns 226, it should be 128 

почему это так?

Согласно Wikipedia и FileFormat ,

  • В ISO-8859-1 отсутствует символ Евро
  • ISO-8859-15 имеет его в коде 164 ( 0xA4 )
  • Windows-1252 имеет код 128 ( 0x80 )
  • Unicode имеет символ евро в 0x20AC 8364 ( 0x20AC )
  • UTF-8 кодирует это как 0xE2 0x82 0xAC . Первый байт E2 равен 226 в десятичном значении.

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

 echo ord('€'); //opposite it returns 226, it should be 128 

Ваш .php-файл сохраняется как UTF-8 (вы сохранили его как UTF-8 в текстовом редакторе при сохранении файла на диске). Строковый литерал там содержит байты E2 82 AC ; визуализировал это что-то вроде этого:

 echo ord('\xE2\x82\xAC'); 

Откройте файл в шестнадцатеричном редакторе для реальной ясности.

ord возвращает только одно целое число в диапазоне от 0 до 255. Ваш строковый литерал содержит три байта, для которых ord должен возвращать три целых числа, а это не будет. Он возвращает только первый, который равен 226 .

Сохраните файл в разных кодировках в текстовом редакторе, и вы увидите разные результаты.

Эта функция PHP возвращает десятичное число первого символа в строке.

  • Если число меньше 128, тогда символ кодируется в 1 октете.
  • Если число меньше 2048, тогда символ кодируется в 2 октетах.
  • Elseif число меньше 65536, тогда символ кодируется в 3 октета.
  • Elseif число ниже 1114112, тогда символ кодируется в 4 октета.

 function ord_utf8($s){ return (int) ($s=unpack('C*',$s[0].$s[1].$s[2].$s[3]))&&$s[1]<(1<<7)?$s[1]: ($s[1]>239&&$s[2]>127&&$s[3]>127&&$s[4]>127?(7&$s[1])<<18|(63&$s[2])<<12|(63&$s[3])<<6|63&$s[4]: ($s[1]>223&&$s[2]>127&&$s[3]>127?(15&$s[1])<<12|(63&$s[2])<<6|63&$s[3]: ($s[1]>193&&$s[2]>127?(31&$s[1])<<6|63&$s[2]:0))); } echo ord_utf8('€'); // Output 8364 then this character is encoded in 3 octets 

Вы можете проверить результат в https://eval.in/748181

Функция ord_utf8 является обратной величиной chr_utf8 (печатает один символ utf8 из десятичного числа)

 function chr_utf8($n,$f='C*'){ return $n<(1<<7)?chr($n):($n<1<<11?pack($f,192|$n>>6,1<<7|191&$n): ($n<(1<<16)?pack($f,224|$n>>12,1<<7|63&$n>>6,1<<7|63&$n): ($n<(1<<20|1<<16)?pack($f,240|$n>>18,1<<7|63&$n>>12,1<<7|63&$n>>6,1<<7|63&$n):''))); } for($test=1;$test<1114111;$test++) if (ord_utf8(chr_utf8($test))!==$test) die('Error found'); echo 'No error'; // Output No error