lua 獲取UTF-8中文字串長度-string.byte
轉載:https://www.jianshu.com/p/be7fa619bb44
一. UTF-8編碼規則
1.1 UTF-8簡單描述
1.2 UTF-8的中文字元編碼如何生成
二、lua 獲取UTF-8字串長度(含中文)
2.1 lua判斷字元是不是中文
2.2 如何取得位元組ASCII碼 - string.byte()
2.3 字元是由幾個位元組組成
2.4 獲取UTF-8字串長度(含示例)
一、UTF-8編碼規則
1.1 UTF-8簡單描述
UTF-8 是 Unicode 的實現方式之一,其對應關係(編碼規則)如下表所示:
Unicode 可以容納100多萬個符號
Unicode符號範圍 | UTF-8位元組數 | UTF-8編碼方式(二進位制) |
---|---|---|
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個位元組表示一個符號,根據不同的符號而變化位元組長度。
- 對於單位元組的符號,位元組的第一位設為0,後面7位為這個符號的 Unicode 碼。取值0-127,與標準ASCII 碼一一對應。標準ASCII 碼錶見附錄。
- 對於n位元組的符號(n > 1),第一個位元組的前n位都設為1,第n + 1位設為0,後面位元組的前兩位一律設為10。剩下的沒有提及的二進位制位,全部為這個符號的 Unicode 碼。
1.2 UTF-8的中文字元編碼如何生成
例如 將中
,龍
兩個字從Unicode轉換為UTF-8:
- 中 : Unicode 是
0x4E2D
(0100 1110 0010 1101
),根據上表,處於第三行範圍內,UTF-8編碼需要三個位元組,格式為1110xxxx 10xxxxxx 10xxxxxx
。
將中
的Unicode 二進位制填充進這個格式,得到11100100 10111000 10101101
,轉換為十進位制是228,184,173
print(string.char(228,184,173))
=>中
- 龍 : Unicode 是
0x9F99
(1001 1111 1001 1001
) ,同樣處於第三行範圍內。
UTF-8編碼為11101001 10111110 10011001
(233,190,153
)print(string.char(233,190,153))
=>龍
input.png
out.png
漢字Unicode碼從漢字對應表中查詢
二、lua 獲取UTF-8字串長度(含中文)
到這裡,已經知道UTF-8的字元、中文是怎麼生成的了,又出現了2個疑問:
- 在lua中怎麼判斷一個字元是不是中文?
- 這個字元是由幾個位元組組成?
2.1 lua判斷字元是不是中文
通常來說,漢字範圍從0x4E00到0x9FA5,轉換為UTF-8編碼為11100100 10111000 10000000
(228, 184, 128
) 到 11101001 10111110 10100101
(233, 190, 165
)
因此,中文UTF-8編碼用3個位元組表示,要遵守格式:1110xxxx 10xxxxxx 10xxxxxx
即第一個位元組的取值區間為 [11100000
, 11110000
) = [0xe0
, 0xf0
) = [224
, 240
) 左開右閉
後兩個位元組的取值區間為[10000000
, 10111111
] = [0x80
,0xbf
] = [128
, 191
] 開區間
2.2 如何取得位元組ASCII碼 - string.byte()
string.byte()
- 原型:string.byte (s [, i [, j] ])
- 解釋:函式返回字元s[i], s[i+1], ···, s[j]的內部數字編碼(ASCII碼),其中引數i的預設值是1,而引數j的預設值是i。
2.3 字元是由幾個位元組組成
讀取第一個位元組,在以下區間的代表不同的位元組數:(有疑問看1.1表)
- [
0
,0xc0
) 表示這個字元僅由1個位元組構成 - [
0xc0
,0xe0
) 表示這個字元由2個位元組構成 - [
0xe0
,0xf0
) 表示這個字元由3個位元組構成 - [
0xf0
,0xff
) 表示這個字元由4個位元組構成
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 -- 編碼的關係
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)
示例1-程式碼執行.png
-
遊戲中希望把一個漢字當做2個位元組處理
characters("我們We", 2)
(因為1個漢字的寬度和2個字母相仿)
示例-程式碼執行.png
附錄
標準ascii碼錶.jpg