如何在lua中将UTF8字节数组转换为字符串

9

我有一张如下所示的表格

table = {57,55,0,15,-25,139,130,-23,173,148,-24,136,158}

这是由 PHP 的 unpack 函数编码的 UTF-8 字节数组。

unpack('C*',$str);

我该如何将其转换为Lua可读取的UTF-8字符串?


这些数字代表什么?它们应该是UTF-8编码的代码点,你想要转换的实际数字文字,还是其他什么? - greatwolf
它是由PHP的unpack函数解包生成的UTF8编码的字节数组。 - Tony
2个回答

6
Lua没有提供直接将UTF-8字节表转换为UTF-8字符串文字的函数。但是,可以借助于"string.char"函数来轻松地完成此操作:
function utf8_from(t)
  local bytearr = {}
  for _, v in ipairs(t) do
    local utf8byte = v < 0 and (0xff + v + 1) or v
    table.insert(bytearr, string.char(utf8byte))
  end
  return table.concat(bytearr)
end

请注意,lua的标准函数和提供的字符串工具不支持utf-8编码。如果您尝试打印从上述函数返回的utf-8编码字符串,您将只会看到一些奇怪的符号。如果您需要更广泛的utf-8支持,请查看lua wiki中提到的一些库。

1
-1:无法处理3字节和4字节的UTF8字符,例如 U+20AC -> €。 - Phrogz

4

这里有一个全面的解决方案,适用于RFC 3629限制的UTF-8字符集:

do
  local bytemarkers = { {0x7FF,192}, {0xFFFF,224}, {0x1FFFFF,240} }
  function utf8(decimal)
    if decimal<128 then return string.char(decimal) end
    local charbytes = {}
    for bytes,vals in ipairs(bytemarkers) do
      if decimal<=vals[1] then
        for b=bytes+1,2,-1 do
          local mod = decimal%64
          decimal = (decimal-mod)/64
          charbytes[b] = string.char(128+mod)
        end
        charbytes[1] = string.char(vals[2]+decimal)
        break
      end
    end
    return table.concat(charbytes)
  end
end

function utf8frompoints(...)
  local chars,arg={},{...}
  for i,n in ipairs(arg) do chars[i]=utf8(arg[i]) end
  return table.concat(chars)
end

print(utf8frompoints(72, 233, 108, 108, 246, 32, 8364, 8212))
--> Héllö €—

我刚刚用一种更加优雅的实现方式替换了旧的实现方式(在二进制数学中不使用字符串),代码更短,因此速度也快了约5倍。 - Phrogz
额外的优化(编辑到上面)提供了另外2倍或更多的性能增益。 - Phrogz
1
如何使用此函数处理类似 s="\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0" 的字符串。 - Алекс Денькин

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接