ChineseUtil 是 PHP 中文工具包,支持漢字轉拼音、拼音分詞、簡繁互轉、數字轉換、金額數字轉換。php
因爲中文的博大精深,字有多音字,簡體字和繁體字也有多種對應。而且本類庫返回的全部結果,均爲包含全部組合的數組。git
本類庫字典數據總共收錄 73925 個漢字,包括:3955 個簡體字,1761 個繁體字,68209 個其它漢字。github
Github:https://github.com/Yurunsoft/...算法
v2.0.0 (2020-08-17)shell
本次更新,重磅推出了 FFI 支持。FFI 動態庫 C++ 代碼:https://github.com/Yurunsoft/...數組
2020 年 7 月份開始想研究 C++,那麼研究點什麼好呢。想着反哺一下 PHP 生態,那麼就爲我以前開發的 ChineseUtil 提高一下性能吧。composer
因而有了一個多月的折騰研究,起初是折騰 C++ 項目的配置。函數
而後是開發了 FFI C 函數,效果不是很理想。性能甚至都不如 PHP 算法,緣由是 FFI 轉換字符串數組,甚至是二維數組,效率實在是過低而且麻煩,有內存泄漏風險。工具
通過一番研究,嘗試了一下目前的方案,也就是調用 zend_register_functions() 函數來動態建立 PHP 函數。性能
相似於 PHP 擴展的開發,可是是經過 FFI 來建立的。
那麼問題來了,爲啥不直接作成 PHP 擴展?
個人本意呢,是讓 ChineseUtil 這個庫能夠開箱即用,不須要編譯、啓用擴展啥的,麻煩。
PHP dl() 函數也能夠動態加載擴展,可是不少環境中是被禁用的。
那麼 FFI 來動態建立 PHP 函數,就成了最佳方案(也許)。
使用 SQLite 做爲數據載體,一次性加載全部數據到變量,內存佔用高(80+ MB),性能最佳。
適合用於運行 Cli 任務。
須要 PDO 和 PDO_SQLITE 擴展支持。
使用 SQLite 做爲數據載體,每次查詢都經過 SQL 查詢,內存佔用低(100-200 KB),性能中等。
適合用於大部分場景。
須要 PDO 和 PDO_SQLITE 擴展支持。
使用精簡過的 JSON 數據做爲數據載體,一次性加載全部數據到變量,內存佔用中(30+ MB),性能差。
內存佔用量以實際爲準,根據版本、擴展等環境的不一樣,佔用的內存容量不同,上述值爲我電腦上的狀況,僅供參考。
適合沒法使用 PDO 的場景。
因爲精簡了數據,一些拼音結果須要通過代碼計算處理才能夠得出,因此性能較差。
須要 PHP >= 7.4 而且啓用 FFI 擴展,代碼所有由 C++ 開發,性能和內存佔用都比 PHP 實現的要好。
FFI 動態庫 C++ 代碼: https://github.com/Yurunsoft/...
須要 PHP >= 7.4 而且啓用 FFI、Swoole 擴展,代碼所有由 C++ 開發,性能和內存佔用都比 PHP 實現的要好。
不會阻塞 PHP 代碼所在線程。
默認狀況下,優先使用通用模式,若是環境不支持 PDO 將採用兼容模式。
你能夠在未執行任何初始化或者轉換處理以前,設置使用何種模式運行。
// 設爲性能模式 Chinese::setMode('Memory'); // 設爲通用模式 Chinese::setMode('SQLite'); // 設爲兼容模式 Chinese::setMode('JSON'); // 設爲 FFI 模式 Chinese::setMode('FFI'); // 設爲Swoole FFI 模式 Chinese::setMode('SwooleFFI');
不管何種模式,拼音分詞所需數據老是從 JSON 數據中加載。
composer require yurunsoft/chinese-util
"require": { "yurunsoft/chinese-util" : "~1.1" }
use \Yurun\Util\Chinese; use \Yurun\Util\Chinese\Pinyin; $string = '恭喜發財!123'; echo $string, PHP_EOL; echo '全拼:', PHP_EOL; var_dump(Chinese::toPinyin($string, Pinyin::CONVERT_MODE_PINYIN)); echo '首字母:', PHP_EOL; var_dump(Chinese::toPinyin($string, Pinyin::CONVERT_MODE_PINYIN_FIRST)); echo '讀音:', PHP_EOL; var_dump(Chinese::toPinyin($string, Pinyin::CONVERT_MODE_PINYIN_SOUND)); echo '讀音數字:', PHP_EOL; var_dump(Chinese::toPinyin($string, Pinyin::CONVERT_MODE_PINYIN_SOUND_NUMBER)); echo '自選返回格式 + 以文本格式返回 + 自定義分隔符:', PHP_EOL; var_dump(Chinese::toPinyin($string, Pinyin::CONVERT_MODE_PINYIN | Pinyin::CONVERT_MODE_PINYIN_SOUND_NUMBER, ' ')); echo '全部結果:', PHP_EOL; var_dump(Chinese::toPinyin($string)); echo '不分割無拼音字符:', PHP_EOL; var_dump(Chinese::toPinyin($string, Pinyin::CONVERT_MODE_PINYIN, ' ', false)); // 結果太長,請自行運行代碼查看
結果是字符串:
use \Yurun\Util\Chinese; $string2 = 'xianggang'; echo '"', $string2, '"的分詞結果:', PHP_EOL; var_dump(Chinese::splitPinyin($string2));
輸出結果:
"xianggang"的分詞結果: array(2) { [0]=> string(11) "xiang gang" [1]=> string(12) "xi ang gang" }
結果是數組:
use \Yurun\Util\Chinese; $string2 = 'xianggang'; echo '"', $string2, '"的分詞結果:', PHP_EOL; var_dump(Chinese::splitPinyinArray($string2));
輸出結果:
"xianggang"的分詞結果: array(2) { [0]=> array(2) { [0]=> string(5) "xiang" [1]=> string(4) "gang" } [1]=> array(3) { [0]=> string(2) "xi" [1]=> string(3) "ang" [2]=> string(4) "gang" } }
use \Yurun\Util\Chinese; $string3 = '中華人民共和國!恭喜發財!'; echo '"', $string3, '"的簡體轉換:', PHP_EOL; var_dump(Chinese::toSimplified($string3)); echo '"', $string3, '"的繁體轉換:', PHP_EOL; var_dump(Chinese::toTraditional($string3));
輸出結果:
"中華人民共和國!恭喜發財!"的簡體轉換: array(1) { [0]=> string(39) "中華人民共和國!恭喜發財!" } "中華人民共和國!恭喜發財!"的繁體轉換: array(1) { [0]=> string(39) "中華人民共和國!恭喜發財!" }
use Yurun\Util\Chinese\Number; function test($number) { $chinese = Number::toChinese($number, [ 'tenMin' => true, // 「一十二」 => 「十二」 ]); $afterNumber = Number::toNumber($chinese); echo $number, '=>', $chinese, '=>', $afterNumber, '=>', 0 === bccomp($number, $afterNumber, 20) ? 'true' : 'false', PHP_EOL; } test(1.234); test(-1234567890.666); test(pi());
輸出結果:
1.234=>一點二三四=>1.234=>true -1234567890.666=>負十二億三千四百五十六萬七千八百九十點六六六=>-1234567890.666=>true 3.1415926535898=>三點一四一五九二六五三五八九八=>3.1415926535898=>true
use Yurun\Util\Chinese\Money; function test($number) { $chinese = Money::toChinese($number, [ 'tenMin' => true, // 「一十二」 => 「十二」 ]); $afterMoney = Money::toNumber($chinese); echo $number, '=>', $chinese, '=>', $afterMoney, '=>', 0 === bccomp($number, $afterMoney) ? 'true' : 'false', PHP_EOL; } test(1.234); test(-1234567890.666);
輸出結果:
輸出結果: 1.234=>壹圓貳角叄分肆釐=>1.234=>true -1234567890.666=>負壹拾貳億叄仟肆佰伍拾陸萬柒仟捌佰玖拾圓陸角陸分陸釐=>-1234567890.666=>true