Lua 編碼 CodePage CP936 Unicode UTF8 及 相關庫library 整理


不常用,查了又忘,遇到時又抓狂,記錄下,疑問請留言。內容來自經驗總結,盲人摸象,不系統,不正確。果然忘了,解決方案在最后一段。

環境

Lua 5.3(Lua文檔/文件UTF8),Win 10(CP936),ZeroBrane Studio(CP936)。

字符對應編碼

字符(符號/character)與編碼(code)相互映射。字符-編碼->編碼、編碼-解碼->字符。

編碼可展現為數值(十進制、十六進制等),以字節(byte)為單位,一個字符的編碼為一個或多個字節。

從編碼的角度,可稱為碼表

字符被組織的角度,可稱為字符集

字符碼表中的編碼,被稱為編碼位置(簡稱碼位/code point/code position)。

一個字符可以被多個碼表描述,對應多種編碼

參考:漢字字符集編碼查詢;中文字符集編碼:GB2312、BIG5、GBK、GB18030、Unicode

字符"·"的GB2312編碼:無,BIG5編碼:A150,GBK編碼:A1A4,GB18030編碼:A1A4,Unicode編碼:B7

字符""的GB2312編碼:D6D0,BIG5編碼:A4A4,GBK編碼:D6D0,GB18030編碼:D6D0,Unicode編碼:4E2D

Windows系統中碼表稱為代碼頁

CHCP命令可查看、設置系統代碼頁

命令chcp.com位於C:\Windows\System32\chcp.com

此路徑被包含於PATH環境變量下,可在命令行CMD、Lua Shellos.execute使用。

Unicode,一個具體的碼表,包含所有字符及其編碼

Lua文檔/文件/代碼中的字面字符字面量/literal string)受Lua文件編碼的影響(稱為硬編碼)。

如,字符"·"在utf8編碼的文件中編碼194,183,在CP936編碼的文件中編碼為161,164

Lua中可在字面量字符串中嵌入顯式地指定編碼(byte單元),形如"\xXX"(十六進制)或"\ddd"(十進制)。

則,在utf8編碼的文件中,有assert("·"=="\194\183");在CP936編碼的文件中,有assert("·"=="\161\164")

類似的,可在字面量字符串中嵌入顯式指定的utf8(二次編碼的Unicode)編碼,形如"\u{XXX}"

參見Lua手冊,3.1 – Lexical Conventions

The UTF-8 encoding of a Unicode character can be inserted in a literal string

以上嵌入編碼不經過Lua文件字符解析,不受指定的文件編碼的影響。

代碼頁(CodePage/CP)一個個具體的碼表,各自包含一定范圍的字符及其編碼

一定范圍的字符包含所有字符的Unicode的子集。

代碼頁中的字符是Unicode的子集,但其編碼不一定與Unicode編碼相同。

如中文字符集(代碼頁/CP936),包含中文環境涉及的字符,英文字符、中文字符等,其中英文字符的代碼頁編碼或與Unicode編碼一致,而中文字符的編碼不一致。

代碼頁中的字符是Unicode的子集(描述的字符范圍較Unicode小),進而,存儲空間小、編碼/解碼時間短。

叫做代碼頁,是因為定義的各代碼頁是按數字編號的。CP1、CP2、..CP936..、CP65000、CP65001。

其中CP0為當前設定的系統/環境代碼頁,CP65001為UTF-8(參見如下utf-8)。

GB2312/GBK是不同版本的中國標准(國標)碼表。

GBK版本更高,兼容GB2312。

GBK被Unicode采納收錄到CP936

其他還有更新的GB18030(收錄於CP54936)。

utf-8是壓縮/再編碼/重編碼/二次編碼/轉換方法。

固定長度的某編碼轉換為一個多個8位二進制單元的變長度編碼。

codepoint/unicode與utf8轉換是雙向等價可逆的。

參考如下不同庫(github pure lua 庫1庫2)中的函數名稱:

codepoint_to_utf8(codepoint)utf8_to_codepoint(string,index)

unicode.encodeunicode.decode

utf8_to_unicode(srcstr)unicode_to_utf8(srcstr)

UTF8(僅?)用於Unicode。codepoint為任意編碼(或特指Unicode?)

codepoint_to_utf8'·'報錯'out of range'?CP936不能轉utf8?

相關搜索:

PHP開發中編碼問題探討_跡憶博客(UTF-8被誤判為CP936)

php cp936轉utf8編碼轉換亂碼問題的解決方案_南通SEO-CSDN博客(作為latin1//IGNORE再轉UTF8)

詭異的 CP936 編碼無法轉換成 UTF-8 - V2EX(不要看print的結果,看原始HEX)

CP936UTF8Unicode相互關系

UTF8與Unicode可以靠算法相互轉換。UTF8可以看作Unicode的壓縮形式。

CP936與Unicode是不同的碼表,需要查表轉換。

Unicode.org-CP936描述了CP936編碼與Unicode編碼(及Unicode字符名的對應關系)。

不同編碼值有各自的特征,可以通過掃描編碼值推斷出可能的編碼方式,但不完全准確。

如(以上提及的第三方庫)utf8.validate(str, byte_pos)可以驗證字符串是否為utf8編碼。

Lua中的編碼

如:utf8編碼下,有assert('·'=='\194\183' and '·'=='\u{b7}')

string.byte (s [, i [, j]])

string.byte (char,1,#char)可以獲得字符char的編碼。

參見Lua手冊:

Returns the internal numeric codes of the characters s[i], s[i+1], ..., s[j].

其中,internal numeric codes即字符的編碼

如utf8編碼的lua文件中的字符"·",string.byte ('·',1,#'·')得194,183;CP936編碼的此字符,得161,164

string.char(byte,..)

string.byte操作的逆操作,將編碼解碼為字符。

string.char(194,183)所得字符在utf8下為"·",在其他編碼下無意義。

local char='·'
local bytes={string.byte (char,1,#char)}
assert(bytes[1]==194 and bytes[2]==183)--UTF8 194, 183 (0xA1A4)
assert(string.char(table.unpack(bytes))==char)

print(...)

能接受uft8編碼或系統代碼頁(CP936)編碼輸入,並正確輸出字符。

如,print'\194\183'(utf8)、print'\161\164'(CP936)輸出"·"。

貌似會自動/隱式地識別處理utf8編碼。故,不可用其檢查編碼問題。

ZeroBrane Studio(ZBS)調試中,會按文件編碼(此處為utf8)顯式字符串。

如,'\194\183'顯示為"·",'\161\164'顯示為'\161\164'。

部分Lua原生、第三方庫函數不支持utf8編碼。

如:io.openio.popenlfs.attributeslfs.dir輸入字符串需為系統活動代碼頁(CP936),不支持傳入/輸入utf8編碼的中文文件路徑;

而,lfs.dir輸出(文件夾中文件、子文件夾的名字字符串)為系統激活代碼頁(CP936)。

assert(select(2,io.open[[G:\PathNotExist]]):find'No such file or directory')
assert(select(2,io.open[[G:\中 文.txt]]):find'Invalid argument')
assert(io.open'G:\\\xD6\xD0 \xCE\xC4.txt')--手動硬編碼指定 GBK/CP936
assert(select(2,io.open'G:\\\u{4e2d} \u{6587}.txt'):find'Invalid argument')--unicode

區分返回的錯誤信息'No such file or directory','Invalid argument'。

即,io.open函數的輸入參數需要CP936編碼,不可UTF8、Unicode編碼。

使用如下的gbk.dllgutf8庫解決。

相關

perfgao/lua-resty-unicode - 碼雲 - 開源中國

unicode.encode'·'--\u00b7

unicode.decode'\\u00b7'--"·"

utf8.lua · Github,擴展lua標准字符串庫(正則等),使支持utf8,純Lua實現。

Egor-Skriptunoff/utf8_filenames.lua · Github

擴展Lua標准庫,使支持utf8編碼輸入。核心是其中的convert_from_utf8,可以提取用於擴展lfs。

starwing \ luagbk - GBK support for Lua · GitHub,高完成度,(gbk/CP936與UTF8的)編碼轉換

starwing \ luautf8 - GUTF-8 module for Lua 5.x · GitHub,高完成度,擴展lua標准字符串庫(正則等),加入其他UTF8專用函數

其他未歸入正文的參考鏈接:

utf-8 和 cp936的區別

utf 8 - How to convert windows-1256 to utf-8 in lua? - Stack Overflow

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM