zoukankan      html  css  js  c++  java
  • 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:WindowsSystem32chcp.com

    此路径被包含于PATH环境变量下,可在命令行CMD、Lua Shellos.execute使用。

    Unicode,一个具体的码表,包含所有字符及其编码

    Lua文档/文件/代码中的字面字符字面量/literal string)受Lua文件编码的影响(称为硬编码)。

    如,字符"·"在utf8编码的文件中编码194,183,在CP936编码的文件中编码为161,164

    Lua中可在字面量字符串中嵌入显式地指定编码(byte单元),形如"xXX"(十六进制)或"ddd"(十进制)。

    则,在utf8编码的文件中,有assert("·"=="194183");在CP936编码的文件中,有assert("·"=="161164")

    类似的,可在字面量字符串中嵌入显式指定的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('·'=='194183' 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'194183'(utf8)、print'161164'(CP936)输出"·"。

    貌似会自动/隐式地识别处理utf8编码。故,不可用其检查编码问题。

    ZeroBrane Studio(ZBS)调试中,会按文件编码(此处为utf8)显式字符串。

    如,'194183'显示为"·",'161164'显示为'161164'。

    部分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:\xD6xD0 xCExC4.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

     

  • 相关阅读:
    基础抽象代数
    斜堆
    WC2018
    WC2019
    有向图上不相交路径计数
    生成树计数
    Prüfer序列
    反演
    1.1 Linux中的进程 --fork、孤儿进程、僵尸进程、文件共享分析
    Python程序的执行过程 解释型语言和编译型语言
  • 原文地址:https://www.cnblogs.com/RobertL/p/13992521.html
Copyright © 2011-2022 走看看