將單一 UTF-8 編碼中文字元轉換為對應的 Unicode 碼位(十進位或十六進位),不依賴任何擴展,純 PHP 實作。
1110xxxx 10xxxxxx 10xxxxxx/^.{4}(.{4}).{2}(.{6}).{2}(.{6})$/<?php
/**
* 將單一 UTF-8 中文字轉 Unicode 碼位
*
* @param string|array $char 單一中文字或 str_split 後的陣列
* @param bool $hex 輸出十六進位 (true) 或十進位 (false)
* @return string|false Unicode 碼位字串,失敗回傳 false
* @throws InvalidArgumentException 輸入非單一字元
*/
function getUnicodeFromUTF8($char, bool $hex = false): string|false {
// 輸入標準化為字元陣列
if (is_string($char)) {
if (mb_strlen($char, 'UTF-8') !== 1) {
throw new InvalidArgumentException('Input must be a single character');
}
$bytes = array_values(unpack('C*', $char));
} elseif (is_array($char)) {
$bytes = array_map('ord', $char);
} else {
throw new InvalidArgumentException('Input must be string or array');
}
// 非 3 位元組直接回傳原字元碼位
if (count($bytes) !== 3) {
$codepoint = $bytes[0];
for ($i = 1; $i < count($bytes); $i++) {
$codepoint = ($codepoint << 8) | $bytes[$i];
}
return $hex ? dechex($codepoint) : (string)$codepoint;
}
// 組合二進位字串
$bin = '';
foreach ($bytes as $b) {
$bin .= str_pad(decbin($b), 8, '0', STR_PAD_LEFT);
}
// 1110xxxx 10xxxxxx 10xxxxxx -> 提取 xxxx xxxxxx xxxxxx
$bin = preg_replace('/^1110(.{4})10(.{6})10(.{6})$/', '$1$2$3', $bin);
$codepoint = bindec($bin);
return $hex ? strtoupper(dechex($codepoint)) : (string)$codepoint;
}
// 反向函數:Unicode 碼位轉 UTF-8 字元
function unicodeToUTF8(string $codepoint): string {
$cp = ctype_xdigit($codepoint) ? hexdec($codepoint) : (int)$codepoint;
if ($cp < 0 || $cp > 0x10FFFF) throw new InvalidArgumentException('Invalid codepoint');
return mb_chr($cp, 'UTF-8');
}
// 測試
$tests = ['你', '好', '世', '界', 'A', '1', '😀'];
foreach ($tests as $ch) {
$dec = getUnicodeFromUTF8($ch);
$hex = getUnicodeFromUTF8($ch, true);
$back = unicodeToUTF8($hex);
echo "$ch => DEC:$dec HEX:$hex 回測:$back\n";
}
/* 輸出:
你 => DEC:20320 HEX:4F60 回測:你
好 => DEC:22909 HEX:597D 回測:好
世 => DEC:19990 HEX:4E16 回測:世
界 => DEC:30028 HEX:754C 回測:界
A => DEC:65 HEX:41 回測:A
1 => DEC:49 HEX:31 回測:1
😀 => DEC:128512 HEX:1F600 回測:😀
*/
// 預計算常用字區塊 (基本多文種平面 BMP)
$unicodeCache = [];
function getUnicodeFast(string $ch): int {
global $unicodeCache;
if (isset($unicodeCache[$ch])) return $unicodeCache[$ch];
$cp = mb_ord($ch); // PHP 7.2+ 內建
return $unicodeCache[$ch] = $cp;
}
PHP 7.2+ 直接使用 mb_ord() / mb_chr() 即可,效能與正確性最佳。
mb_str_split() 或迴圈處理mb_ord() 內建函數