【问题标题】:converting UTF-8 string to ASCII in pure LUA在纯 LUA 中将 UTF-8 字符串转换为 ASCII
【发布时间】:2017-06-10 21:13:22
【问题描述】:

我有一个关于发送和接收带有特殊字符的数据的问题。 (德语变音)

当我使用下面的代码发送字符串“Café Zeezicht”时,在服务器端该字符串正常。

但是如何接收和解码包含相同字符的接收数据?现在它看起来像“Caf? Zeezicht”

我正在寻找一个纯 LUA 函数,因为我没有能力加载库。

------------------------------------------------------------
-- Function voor converting ASCII naar UTF8
------------------------------------------------------------

-- return char as utf8 string
local function CodeToUTF8 (Unicode)
  if (Unicode == nil) then 
    return ""
  end

  if (Unicode < 0x20) then return ' '; end;

    if (Unicode <= 0x7F) then return string.char(Unicode); end;

    if (Unicode <= 0x7FF) then
      local Byte0 = 0xC0 + math.floor(Unicode / 0x40);
      local Byte1 = 0x80 + (Unicode % 0x40);
      return string.char(Byte0, Byte1);
    end;

    if (Unicode <= 0xFFFF) then
      local Byte0 = 0xE0 +  math.floor(Unicode / 0x1000);
      local Byte1 = 0x80 + (math.floor(Unicode / 0x40) % 0x40);
      local Byte2 = 0x80 + (Unicode % 0x40);
      return string.char(Byte0, Byte1, Byte2);
    end;

    return "";    -- ignore UTF-32 for the moment
end;


-- convert ascii string to utf8 string
function AsciiToUTF8(str)
  result = ""
  for i = 1, #str do
    result = result .. CodeToUTF8(string.byte(str, i, i+1))
  end
  return result
end
------------------------------------------------------------
-- Einde Function voor converting ASCII naar UTF8
------------------------------------------------------------

【问题讨论】:

    标签: utf-8 lua ascii


    【解决方案1】:
    local char, byte, pairs, floor = string.char, string.byte, pairs, math.floor
    local table_insert, table_concat = table.insert, table.concat
    local unpack = table.unpack or unpack
    
    local function unicode_to_utf8(code)
       -- converts numeric UTF code (U+code) to UTF-8 string
       local t, h = {}, 128
       while code >= h do
          t[#t+1] = 128 + code%64
          code = floor(code/64)
          h = h > 32 and 32 or h/2
       end
       t[#t+1] = 256 - 2*h + code
       return char(unpack(t)):reverse()
    end
    
    local function utf8_to_unicode(utf8str, pos)
       -- pos = starting byte position inside input string (default 1)
       pos = pos or 1
       local code, size = utf8str:byte(pos), 1
       if code >= 0xC0 and code < 0xFE then
          local mask = 64
          code = code - 128
          repeat
             local next_byte = utf8str:byte(pos + size) or 0
             if next_byte >= 0x80 and next_byte < 0xC0 then
                code, size = (code - mask - 2) * 64 + next_byte, size + 1
             else
                code, size = utf8str:byte(pos), 1
             end
             mask = mask * 32
          until code < mask
       end
       -- returns code, number of bytes in this utf8 char
       return code, size
    end
    
    local map_1252_to_unicode = {
       [0x80] = 0x20AC,
       [0x81] = 0x81,
       [0x82] = 0x201A,
       [0x83] = 0x0192,
       [0x84] = 0x201E,
       [0x85] = 0x2026,
       [0x86] = 0x2020,
       [0x87] = 0x2021,
       [0x88] = 0x02C6,
       [0x89] = 0x2030,
       [0x8A] = 0x0160,
       [0x8B] = 0x2039,
       [0x8C] = 0x0152,
       [0x8D] = 0x8D,
       [0x8E] = 0x017D,
       [0x8F] = 0x8F,
       [0x90] = 0x90,
       [0x91] = 0x2018,
       [0x92] = 0x2019,
       [0x93] = 0x201C,
       [0x94] = 0x201D,
       [0x95] = 0x2022,
       [0x96] = 0x2013,
       [0x97] = 0x2014,
       [0x98] = 0x02DC,
       [0x99] = 0x2122,
       [0x9A] = 0x0161,
       [0x9B] = 0x203A,
       [0x9C] = 0x0153,
       [0x9D] = 0x9D,
       [0x9E] = 0x017E,
       [0x9F] = 0x0178,
       [0xA0] = 0x00A0,
       [0xA1] = 0x00A1,
       [0xA2] = 0x00A2,
       [0xA3] = 0x00A3,
       [0xA4] = 0x00A4,
       [0xA5] = 0x00A5,
       [0xA6] = 0x00A6,
       [0xA7] = 0x00A7,
       [0xA8] = 0x00A8,
       [0xA9] = 0x00A9,
       [0xAA] = 0x00AA,
       [0xAB] = 0x00AB,
       [0xAC] = 0x00AC,
       [0xAD] = 0x00AD,
       [0xAE] = 0x00AE,
       [0xAF] = 0x00AF,
       [0xB0] = 0x00B0,
       [0xB1] = 0x00B1,
       [0xB2] = 0x00B2,
       [0xB3] = 0x00B3,
       [0xB4] = 0x00B4,
       [0xB5] = 0x00B5,
       [0xB6] = 0x00B6,
       [0xB7] = 0x00B7,
       [0xB8] = 0x00B8,
       [0xB9] = 0x00B9,
       [0xBA] = 0x00BA,
       [0xBB] = 0x00BB,
       [0xBC] = 0x00BC,
       [0xBD] = 0x00BD,
       [0xBE] = 0x00BE,
       [0xBF] = 0x00BF,
       [0xC0] = 0x00C0,
       [0xC1] = 0x00C1,
       [0xC2] = 0x00C2,
       [0xC3] = 0x00C3,
       [0xC4] = 0x00C4,
       [0xC5] = 0x00C5,
       [0xC6] = 0x00C6,
       [0xC7] = 0x00C7,
       [0xC8] = 0x00C8,
       [0xC9] = 0x00C9,
       [0xCA] = 0x00CA,
       [0xCB] = 0x00CB,
       [0xCC] = 0x00CC,
       [0xCD] = 0x00CD,
       [0xCE] = 0x00CE,
       [0xCF] = 0x00CF,
       [0xD0] = 0x00D0,
       [0xD1] = 0x00D1,
       [0xD2] = 0x00D2,
       [0xD3] = 0x00D3,
       [0xD4] = 0x00D4,
       [0xD5] = 0x00D5,
       [0xD6] = 0x00D6,
       [0xD7] = 0x00D7,
       [0xD8] = 0x00D8,
       [0xD9] = 0x00D9,
       [0xDA] = 0x00DA,
       [0xDB] = 0x00DB,
       [0xDC] = 0x00DC,
       [0xDD] = 0x00DD,
       [0xDE] = 0x00DE,
       [0xDF] = 0x00DF,
       [0xE0] = 0x00E0,
       [0xE1] = 0x00E1,
       [0xE2] = 0x00E2,
       [0xE3] = 0x00E3,
       [0xE4] = 0x00E4,
       [0xE5] = 0x00E5,
       [0xE6] = 0x00E6,
       [0xE7] = 0x00E7,
       [0xE8] = 0x00E8,
       [0xE9] = 0x00E9,
       [0xEA] = 0x00EA,
       [0xEB] = 0x00EB,
       [0xEC] = 0x00EC,
       [0xED] = 0x00ED,
       [0xEE] = 0x00EE,
       [0xEF] = 0x00EF,
       [0xF0] = 0x00F0,
       [0xF1] = 0x00F1,
       [0xF2] = 0x00F2,
       [0xF3] = 0x00F3,
       [0xF4] = 0x00F4,
       [0xF5] = 0x00F5,
       [0xF6] = 0x00F6,
       [0xF7] = 0x00F7,
       [0xF8] = 0x00F8,
       [0xF9] = 0x00F9,
       [0xFA] = 0x00FA,
       [0xFB] = 0x00FB,
       [0xFC] = 0x00FC,
       [0xFD] = 0x00FD,
       [0xFE] = 0x00FE,
       [0xFF] = 0x00FF,
    }
    local map_unicode_to_1252 = {}
    for code1252, code in pairs(map_1252_to_unicode) do
       map_unicode_to_1252[code] = code1252
    end
    
    function string.fromutf8(utf8str)
       local pos, result_1252 = 1, {}
       while pos <= #utf8str do
          local code, size = utf8_to_unicode(utf8str, pos)
          pos = pos + size
          code = code < 128 and code or map_unicode_to_1252[code] or ('?'):byte()
          table_insert(result_1252, char(code))
       end
       return table_concat(result_1252)
    end
    
    function string.toutf8(str1252)
       local result_utf8 = {}
       for pos = 1, #str1252 do
          local code = str1252:byte(pos)
          table_insert(result_utf8, unicode_to_utf8(map_1252_to_unicode[code] or code))
       end
       return table_concat(result_utf8)
    end
    

    用法:

    local str1252 = "1\128"  -- "one euro" in latin-1
    local str_utf8 = str1252:toutf8()     -- "1\226\130\172" -- one euro in utf-8
    local str1252_2 = str_utf8:fromutf8()
    

    【讨论】:

    • Egor Skriptunoff 感谢您的解决方案!我已经实现了上面的功能,它适用于我的情况。
    • 在我的例子中,所有的重音字母都被消除了,包括元音变音等。我真的很挣扎:-/ 不考虑带有重音或“变音”字符的目录名称。因此返回一个名为“tüv-ààéérï-utf8_.wav”的文件“t.v-....r.-utf8_.wav”
    猜你喜欢
    • 2015-08-06
    • 1970-01-01
    • 2012-06-25
    • 2021-12-31
    • 2011-06-19
    • 2010-10-24
    • 2019-06-04
    • 1970-01-01
    • 2019-10-31
    相关资源
    最近更新 更多