UTF8字符串在lua的截取和字数统计【转载】
转载自:GitHub:pangliang/pangliang.github.com
需求
按字面个数来截取
函数(字符串, 开始位置, 截取长度)
utf8sub("你好1世界哈哈",,) = 好1世界哈
utf8sub("1你好1世界哈哈",,) = 你好1世界
utf8sub("你好世界1哈哈",,) = 你好世界1
utf8sub("",,) =
utf8sub("øpø你好pix",,) = pø你好p
错误方法
网上找了一些算法, 都不太正确; 要么就是乱码, 要么就是只考虑了4 byte 中文的情况, 不够全面
1. string.sub(s,1,截取长度*4)
网上很多直接使用"`""string.sub(s,1,截取长度*4)`"是肯定不对的, 因为如果中英文混合的字符串, 例如`你好1世界`的字符长度分别是`4,4,1,4,4`, 如果截取4个字, 4*4=4+4+1+4+3, 那`世界`的`界`字将会被取前3个byte, 就会出现乱码
2. if byte>128 then index = index + 4
问题关键
1. utf8字符是变长字符
2. 字符长度有规律
UTF-8字符规律
字符串的首个byte表示了该utf8字符的长度
0xxxxxxx - 1 byte
110yxxxx - 192, 2 byte
1110yyyy - 225, 3 byte
11110zzz - 240, 4 byte
正确算法
--
-- lua
-- 判断utf8字符byte长度
-- 0xxxxxxx - 1 byte
-- 110yxxxx - 192, 2 byte
-- 1110yyyy - 225, 3 byte
-- 11110zzz - 240, 4 byte
local function chsize(char)
if not char then
print("not char")
return
elseif char > then
return
elseif char > then
return
elseif char > then
return
else
return
end
end -- 计算utf8字符串字符数, 各种字符都按一个字符计算
-- 例如utf8len("1你好") => 3
function utf8len(str)
local len =
local currentIndex =
while currentIndex <= #str do
local char = string.byte(str, currentIndex)
currentIndex = currentIndex + chsize(char)
len = len +
end
return len
end -- 截取utf8 字符串
-- str: 要截取的字符串
-- startChar: 开始字符下标,从1开始
-- numChars: 要截取的字符长度
function utf8sub(str, startChar, numChars)
local startIndex =
while startChar > do
local char = string.byte(str, startIndex)
startIndex = startIndex + chsize(char)
startChar = startChar -
end local currentIndex = startIndex while numChars > and currentIndex <= #str do
local char = string.byte(str, currentIndex)
currentIndex = currentIndex + chsize(char)
numChars = numChars -
end
return str:sub(startIndex, currentIndex - )
end -- 自测
function test()
-- test utf8len
assert(utf8len("你好1世界哈哈") == )
assert(utf8len("你好世界1哈哈 ") == )
assert(utf8len(" 你好世 界1哈哈") == )
assert(utf8len("") == )
assert(utf8len("øpø你好pix") == ) -- test utf8sub
assert(utf8sub("你好1世界哈哈",,) == "好1世界哈")
assert(utf8sub("1你好1世界哈哈",,) == "你好1世界")
assert(utf8sub(" 你好1世界 哈哈",,) == "你好1世界 ")
assert(utf8sub("你好世界1哈哈",,) == "你好世界1")
assert(utf8sub("",,) == "")
assert(utf8sub("øpø你好pix",,) == "pø你好p") print("all test succ")
end test()
UTF8字符串在lua的截取和字数统计【转载】的更多相关文章
- [寒江孤叶丶的Cocos2d-x之旅_36]用LUA实现UTF8的字符串基本操作 UTF8字符串长度,UTF8字符串剪裁等
原创文章,欢迎转载,转载请注明:文章来自[寒江孤叶丶的Cocos2d-x之旅系列] 博客地址:http://blog.csdn.net/qq446569365 一个用于UTF8字符串操作的类.功能比較 ...
- php字符串标点等字符截取不乱吗 封装方法
方法一: /** +---------------------------------------------------------- * 功能:字符串截取指定长度 * leo.li hen ...
- c++ 处理utf-8字符串
c++的字符串中的每一个元素都是一个字节.所以在装入utf8字符串的时候,其实是按照一定的规则编码的. 字符的8位中 如果0开头 则自己就是一个单位. 1字节 0xxxxxxx 2字节 110xxx ...
- 11、多行文本最后一行显示省略号并截取文本字数(vue)
1.首先通过css实现多行文本显示省略号: { height: 45px; display: -webkit-box; -webkit-box-orient: vertical; -webkit-li ...
- UTF-8编码的字符串拆分成单字、获取UTF-8字符串的字符个数的代码及原理
一.字符编码简介 1. ASCII码 在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(by ...
- [C++] zlatlcv: ATL字符串转换辅助库。能很方便的将UTF-8字符串转为TCHAR等字符串
作者:zyl910 如今,UTF-8字符串的使用频率越来越多了.但是在VC中,不能直接处理UTF-8字符串,得专门去写UTF-8与窄字符串.宽字符串.TCHAR字符串相互转换的代码.不仅费时费力,而且 ...
- UTF8字符串转换为汉字 c#
using System; /// <summary> /// UTF8字符串转换为汉字用的类 /// 转换如"\\u8d35"之类的字符串为对应的汉字 /// < ...
- 【转】UTF8字符串转换为汉字 c#,转自游戏开发主席
using System; /// <summary> /// UTF8字符串转换为汉字用的类 /// 转换如"\\u8d35"之类的字符串为对应的汉字 /// < ...
- c语言判断是否是utf8字符串,计算字符个数
#include <stdio.h> #include <string.h> #include <stdlib.h> /********************** ...
随机推荐
- Mount 挂载错误mount:block device /dev/sr0 is write – protected , mounting read-only
Mount 挂载错误mount:block device /dev/sr0 is write – protected , mounting read-only 安装虚拟机出现以下提示: mount:b ...
- [Done]SnowFlake 分布式环境下基于ZK构WorkId
Twitter 的 Snowflake 大家应该都熟悉的,先上个图: 时间戳 序列号一般不会去改造,主要是工作机器id,大家会进行相关改造,我厂对工作机器进行了如下改造(估计大家都差不多吧,囧~~~ ...
- Centos5, 6, 以及Ubuntu18.04下更改系统时间和时区
http://www.namhuy.net/2435/how-to-change-date-time-timezone-on-centos-6.html 查看日期(使用 -R 参数会以数字显示时区) ...
- Android API之android.provider.ContactsContract
android.provider.ContactsContract ContactsContract是联系人provider和app的contract.定义了已支持的URL和column.取代了之前的 ...
- HDUOJ----1170Milk
Milk Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- Redis基本操作——List
Redis基本操作——List(原理篇) 学习过数据结构的同学,一定对链表(Linked List)十分的熟悉.相信我们自己也曾经使用过这种数据结构. 链表分为很多种:单向链表,双向链表,循环链表,块 ...
- Oracle分组函数以及数据分组
简单总结一下对于数据的分组和分组函数. 本文所举实例,数据来源oracle用户scott下的emp,dept ,salgrade 3表:数据如下: 一.分组函数 1.sum()求和函数.max()求最 ...
- DBA_实践指南系列7_Oracle Erp R12监控OAM(案例)
2013-12-07 Created By BaoXinjian
- Android中判断网络连接是否可用及监控网络状态
Android中判断网络连接是否可用及监控网络状态 作者: 字体:[增加 减小] 类型:转载 获取网络信息需要在AndroidManifest.xml文件中加入相应的权限,接下来详细介绍Android ...
- 一个进程发起多个连接和gethostbyname等函数
一.在前面讲过的最简单的回射客户/服务器程序中,一个客户端即一个进程,只会发起一个连接,只要稍微修改一下就可以让一个客户端发起多个连 接,然后只利用其中一个连接发送数据. 先来认识一个函数getsoc ...