本文共 1686 字,大约阅读时间需要 5 分钟。
首先要知道string.sub 和 string.byte 的用法。
基本思路:
之所以要自己写一个截取函数,是因为lua的库函数string.sub实际是字节的截取函数。
uft-8编码格式中,大部分中文是3个字节表示的,数字和字母等是一个字节的,还有某些国家的语言是2字节的,直接用string.sub就可能截出乱码来,因为不确定要截多少个字节。
所以,
定义一个GetBytes函数,获取字符的字节数(根据首个字节的高位标记,判断是几字节的字符)
然后不断后移,记录字节数和字符数。
如上图,假设要取字符3-4,那么应该从第3个字符的第一个字节取到第4个字最后一个字节
即:
当前字符数为截取的起始字符(startIndex)前一个位置时,说明从下一个字节开始截取字符串 即 index == startIndex - 1 时 byteStart = bytes+1
当前字符数为截取的终止字符(endIndex)时,说明要截取的字符串到此为止 即 index == endIndex 时 byteEnd = bytes
用 string.sub(str, byteStart, byteEnd) 就能截取byteStart 到 byteEnd 的字节
local StringHelper ={}--[[
utf-8编码规则
单字节-0起头
1字节 0xxxxxxx0 - 127多字节-第一个字节n个1加1个0起头2 字节 110xxxxx 192 - 223
3 字节 1110xxxx 224 - 239
4 字节 11110xxx 240 - 247可能有1-4个字节--]]function StringHelper.GetBytes(char)if not charthenreturn 0end
local code= string.byte(char)if code < 127thenreturn 1elseif code<= 223thenreturn 2elseif code<= 239thenreturn 3elseif code<= 247thenreturn 4
else
-- 讲道理不会走到这里^_^
return 0end
endfunctionStringHelper.Sub(str, startIndex, endIndex)
local tempStr=str
local byteStart= 1 --string.sub截取的开始位置
local byteEnd= -1 --string.sub截取的结束位置
local index= 0 --字符记数
local bytes= 0 --字符的字节记数
startIndex= math.max(startIndex, 1)
endIndex= endIndex or -1
while string.len(tempStr) > 0 do
if index == startIndex - 1then
byteStart= bytes+1;
elseif index==endIndex then
byteEnd=bytes;break;
end
bytes= bytes +StringHelper.GetBytes(tempStr)
tempStr= string.sub(str, bytes+1)
index= index + 1endreturnstring.sub(str, byteStart, byteEnd)
end
测试代码:
str = "中1文*a字符串勉強します";
print(StringHelper.Sub(str, 3, 4))
print(StringHelper.Sub(str, 1, 4))
print(StringHelper.Sub(str, 8))
print(StringHelper.Sub(str, 2, 12))
https://www.cnblogs.com/yougoo/p/11960801.html