萝卜L

导航

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

 

posted on 2020-11-17 16:30  萝卜L  阅读(1754)  评论(0编辑  收藏  举报