目錄:
一. UTF-8編碼規(guī)則
1.1 UTF-8簡單描述
1.2 UTF-8的中文字符編碼如何生成
二宾茂、lua 獲取UTF-8字符串長度(含中文)
2.1 lua判斷字符是不是中文
2.2 如何取得字節(jié)ASCII碼 - string.byte()
2.3 字符是由幾個字節(jié)組成
2.4 獲取UTF-8字符串長度(含示例)
一性含、UTF-8編碼規(guī)則
1.1 UTF-8簡單描述
UTF-8 是 Unicode 的實現(xiàn)方式之一长捧,其對應(yīng)關(guān)系(編碼規(guī)則)如下表所示:
Unicode 可以容納100多萬個符號
Unicode符號范圍 | UTF-8字節(jié)數(shù) | UTF-8編碼方式(二進(jìn)制) |
---|---|---|
0000 0000-0000 007F (0-127) | 1 | 0xxxxxxx |
0000 0080-0000 07FF (128-2047) | 2 | 110xxxxx 10xxxxxx |
0000 0800-0000 FFFF (2048-65535) | 3 | 1110xxxx 10xxxxxx 10xxxxxx |
0001 0000-0010 FFFF (65536-1050623) | 4 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
UTF-8 最大的一個特點成玫,就是它是一種變長的編碼方式萍歉。它可以使用1~4個字節(jié)表示一個符號磕道,根據(jù)不同的符號而變化字節(jié)長度膀哲。
- 對于單字節(jié)的符號损拢,字節(jié)的第一位設(shè)為0陌粹,后面7位為這個符號的 Unicode 碼。取值0-127福压,與標(biāo)準(zhǔn)ASCII 碼一一對應(yīng)掏秩。標(biāo)準(zhǔn)ASCII 碼表見附錄。
- 對于n字節(jié)的符號(n > 1)荆姆,第一個字節(jié)的前n位都設(shè)為1蒙幻,第n + 1位設(shè)為0,后面字節(jié)的前兩位一律設(shè)為10胆筒。剩下的沒有提及的二進(jìn)制位邮破,全部為這個符號的 Unicode 碼诈豌。
1.2 UTF-8的中文字符編碼如何生成
例如 將中
,龍
兩個字從Unicode轉(zhuǎn)換為UTF-8:
- 中 : Unicode 是
0x4E2D
(0100 1110 0010 1101
),根據(jù)上表,處于第三行范圍內(nèi)抒和,UTF-8編碼需要三個字節(jié)矫渔,格式為1110xxxx 10xxxxxx 10xxxxxx
。
將中
的Unicode 二進(jìn)制填充進(jìn)這個格式摧莽,得到11100100 10111000 10101101
庙洼,轉(zhuǎn)換為十進(jìn)制是228,184镊辕,173
print(string.char(228,184,173))
=>中
- 龍 : Unicode 是
0x9F99
(1001 1111 1001 1001
) 油够,同樣處于第三行范圍內(nèi)。
UTF-8編碼為11101001 10111110 10011001
(233征懈,190石咬,153
)
print(string.char(233,190,153))
=>龍
漢字Unicode碼從漢字對應(yīng)表中查找
二、lua 獲取UTF-8字符串長度(含中文)
到這里受裹,已經(jīng)知道UTF-8的字符碌补、中文是怎么生成的了,又出現(xiàn)了2個疑問:
- 在lua中怎么判斷一個字符是不是中文棉饶?
- 這個字符是由幾個字節(jié)組成厦章?
2.1 lua判斷字符是不是中文
通常來說,漢字范圍從0x4E00到0x9FA5照藻,轉(zhuǎn)換為UTF-8編碼為11100100 10111000 10000000
(228, 184, 128
) 到 11101001 10111110 10100101
(233, 190, 165
)
因此袜啃,中文UTF-8編碼用3個字節(jié)表示,要遵守格式:1110xxxx 10xxxxxx 10xxxxxx
即第一個字節(jié)的取值區(qū)間為 [11100000
, 11110000
) = [0xe0
, 0xf0
) = [224
, 240
) 左開右閉
后兩個字節(jié)的取值區(qū)間為[10000000
, 10111111
] = [0x80
幸缕,0xbf
] = [128
, 191
] 開區(qū)間
2.2 如何取得字節(jié)ASCII碼 - string.byte()
string.byte()
- 原型:string.byte (s [, i [, j] ])
- 解釋:函數(shù)返回字符s[i], s[i+1], ···, s[j]的內(nèi)部數(shù)字編碼(ASCII碼)群发,其中參數(shù)i的默認(rèn)值是1,而參數(shù)j的默認(rèn)值是i发乔。
2.3 字符是由幾個字節(jié)組成
讀取第一個字節(jié)熟妓,在以下區(qū)間的代表不同的字節(jié)數(shù):(有疑問看1.1表)
- [
0
,0xc0
) 表示這個字符僅由1個字節(jié)構(gòu)成 - [
0xc0
,0xe0
) 表示這個字符由2個字節(jié)構(gòu)成 - [
0xe0
,0xf0
) 表示這個字符由3個字節(jié)構(gòu)成 - [
0xf0
,0xff
) 表示這個字符由4個字節(jié)構(gòu)成
local function Bytes4Character(theByte)
local seperate = {0, 0xc0, 0xe0, 0xf0}
for i = #seperate, 1, -1 do
if theByte >= seperate[i] then return i end
end
return 1
end
2.4 獲取UTF-8字符串長度
function characters(utf8Str, aChineseCharBytes)
aChineseCharBytes = aChineseCharBytes or 2
local i = 1
local characterSum = 0
while (i <= #utf8Str) do -- 編碼的關(guān)系
local bytes4Character = Bytes4Character(string.byte(utf8Str, i))
characterSum = characterSum + (bytes4Character > aChineseCharBytes and aChineseCharBytes or bytes4Character)
i = i + bytes4Character
end
return characterSum
end
示例: UTF-8字符串:我們We
,
-
每一個中文算一個字符
characters("我們We", 1)
游戲中希望把一個漢字當(dāng)做2個字節(jié)處理
characters("我們We", 2)
(因為1個漢字的寬度和2個字母相仿)