lua開発--文字列,json,符号化変換

23661 ワード

JSONライブラリ
データ転送時のJSON形式は現在広く応用されているため、LuaオブジェクトとJSON文字列間の相互変換は非常に一般的な機能である.現在LuaにもいくつかのJSONライブラリがあり、本人はcjson、dkjsonを使ったことがある.ここでcjsonの文法は厳格で(例えばunicode<20>u 7 eaf)、要求が規範に合致しないと解析に失敗し(例えば<2)、dkjsonは比較的緩やかで、もちろんcjsonのソースコードを修正することによっていくつかの特殊な要求を完成することができます.dkjsonを使用しても性能の問題はなく、現在はdkjsonを使用しています.使用時に特に注意しなければならないのは、ほとんどのJSONライブラリがUTF-8符号化のみをサポートしていることです.したがって、文字コードがGBKのような場合は、まずUTF-8に変換して処理する必要があります.
1.1、test_cjson.lua
local cjson = require("cjson")

--lua      
local obj = {
    id = 1,
    name = "zhangsan",
    age = nil,
    is_male = false,
    hobby = {"film", "music", "read"}
}

local str = cjson.encode(obj)
ngx.say(str, "
"
) -- lua str = '{"hobby":["film","music","read"],"is_male":false,"name":"zhangsan","id":1,"age":null}' local obj = cjson.decode(str) ngx.say(obj.age, "
"
) ngx.say(obj.age == nil, "
"
) ngx.say(obj.age == cjson.null, "
"
) ngx.say(obj.hobby[1], "
"
) -- obj = { id = 1 } obj.obj = obj -- Cannot serialise, excessive nesting --ngx.say(cjson.encode(obj), "
")
local cjson_safe = require("cjson.safe") --nil ngx.say(cjson_safe.encode(obj), "
"
)

nullはcjsonに変換されます.null;循環参照は異常Cannot serialise,excessive nestingを放出し、デフォルトの解析ネスト深さは1000であり、cjsonを通過することができる.encode_max_depth()深さを設定して性能を向上させる;cjsonを使用します.safeは異常を投げ出すのではなくnilに戻る.
1.2、example.confプロファイル
     location ~ /lua_cjson {
        default_type 'text/html';
        lua_code_cache on;
        content_by_lua_file /usr/example/lua/test_cjson.lua;
     }

1.3、アクセスhttp://192.168.1.2/lua_cjson以下の結果が得られる
{"hobby":["film","music","read"],"is_male":false,"name":"zhangsan","id":1}  
null  
false  
true  
film  
nil 

lua-cjsonドキュメントhttp://www.kyne.com.au/~mark/software/lua-cjson-manual.html.
次にdkjsonを勉強します.2.1、dkjsonライブラリのダウンロード
cd /usr/example/lualib/  
wget http://dkolf.de/src/dkjson-lua.fsl/raw/dkjson.lua?name=16cbc26080996d9da827df42cb0844a25518eeb3 -O dkjson.lua 

2.2、test_dkjson.lua
local dkjson = require("dkjson")

--lua      
local obj = {
    id = 1,
    name = "zhangsan",
    age = nil,
    is_male = false,
    hobby = {"film", "music", "read"}
}

local str = dkjson.encode(obj, {indent = true})
ngx.say(str, "
"
) -- lua str = '{"hobby":["film","music","read"],"is_male":false,"name":"zhangsan","id":1,"age":null}' local obj, pos, err = dkjson.decode(str, 1, nil) ngx.say(obj.age, "
"
) ngx.say(obj.age == nil, "
"
) ngx.say(obj.hobby[1], "
"
) -- obj = { id = 1 } obj.obj = obj --reference cycle --ngx.say(dkjson.encode(obj), "
")

デフォルトで解析されたjsonの文字には縮退と改行があり、{indent=true}構成を使用してすべての内容を1行に配置します.cjsonとは異なり、json文字列のnullを解析するとnilが得られます.
2.3、example.confプロファイル
    location ~ /lua_dkjson {  
       default_type 'text/html';  
       lua_code_cache on;  
       content_by_lua_file /usr/example/lua/test_dkjson.lua;  
    }  

2.4、アクセスhttp://192.168.1.2/lua_dkjson結果{"hobby":["film","music","read","is_male":false,"name":"zhangsan","id":1}nil true film dkjsonドキュメントhttp://dkolf.de/src/dkjson-lua.fsl/homeおよびhttp://dkolf.de/src/dkjson-lua.fsl/wiki?name=Documentation.
コード変換
いくつかのクラスライブラリを使用すると、ほとんどのライブラリはUTF-8符号化のみをサポートしていることがわかります.そのため、他の符号化を使用する場合は、符号化変換の処理が必要です.Linuxで最も一般的なのはiconvであり、lua-iconvはLua APIのパッケージである.
lua-iconvをインストールするには、次の2つの方法があります.
ubuntuでは次のように使用できます.
apt-get install luarocks  
luarocks install lua-iconv   
cp /usr/local/lib/lua/5.1/iconv.so  /usr/example/lualib/ 

ソースコードのインストール方式は、gcc環境のダウンロードアドレスが必要です:https://github.com/ittner/lua-iconv/downloads
wget https://github.com/do^Cloads/ittner/lua-iconv/lua-iconv-7.tar.gz
tar -xvf lua-iconv-7.tar.gz
cd lua-iconv-7
gcc -O2 -fPIC -I/usr/include/lua5.1 -c luaiconv.c -o luaiconv.o -I/usr/include
gcc -shared -o iconv.so -L/usr/local/lib luaiconv.o -L/usr/lib
cp iconv.so  /usr/example/lualib/

1、test_iconv.lua
    ngx.say("  ")  

この場合、ファイル符号化はUTF-8でなければならない.すなわち、Luaファイル符号化はなぜ中の文字符号化が何であるのか.2、example.confプロファイル
     location ~ /lua_iconv {
        default_type 'text/html';
        charset gbk;
        lua_code_cache on;
        content_by_lua_file /usr/example/lua/test_iconv.lua;
     }

charsetを通じてブラウザに私たちの文字がgbkに符号化されていることを伝えます.
3、アクセスhttp://192.168.1.2/lua_iconv出力文字化けしが見つかります.
test_iconv.luaの文字はトランスコード処理を行います:
  local iconv = require("iconv")  
    local togbk = iconv.new("gbk", "utf-8")  
    local str, err = togbk:iconv("  ")  
    ngx.say(str)  

トランスコードにより最終出力のコンテンツをgbkに符号化し、方式iconvを用いる.new(ターゲット符号化、ソース符号化).
次のエラーが発生する可能性があります.
    nil     
              。  
    iconv.ERROR_NO_MEMORY  
            。  
    iconv.ERROR_INVALID  
             。  
    iconv.ERROR_INCOMPLETE  
              。  
    iconv.ERROR_FINALIZED  
                  ,       。  
    iconv.ERROR_UNKNOWN   
              

また、実際の使用中にUTF-8からGBKへの変換プロセスを行うと、一部の文字はGBK符号表では変換できないが、この場合、より高い符号化GB 18030を用いて変換を完了することができる.
詳細については、http://ittner.github.io/lua-iconv/.
ビット演算
Lua 5.3以前はビット演算サポートは提供されていなかったが、LuaJITがbitライブラリを提供しているなどのサードパーティライブラリを使用する必要がある.
1、test_bit.lua
  local bit = require("bit")  
    ngx.say(bit.lshift(1, 2))  

lshiftは左シフト演算を行い,すなわち4を得る.
その他のビット操作APIは参照してくださいhttp://bitop.luajit.org/api.html.Lua 5.3のビット演算オペレータhttp://cloudwu.github.io/lua53doc/manual.html#3.4.2.
cache
ngx_luaモジュール自体はグローバル共有メモリngxを提供する.shared.DICTは、グローバル共有を実現することができ、また、Redisのようなキャッシュを実現するために使用することができる.もう1つのlua-resty-lrucacheはngxと実現する.shared.DICTが異なるのは、ワークごとに共有されていることです.つまり、ワークごとにキャッシュが行われ、実際に使用するとngxに及ばないことがわかります.shared.DICT.しかし、その利点は、グローバル構成を必要としないことです.
1、キャッシュモジュールを作成して一度だけ初期化を実現する:
vim /usr/example/lualib/mycache.lua   
local lrucache = require("resty.lrucache")
--      ,           
local cache, err = lrucache.new(200)
if not cache then
   ngx.log(ngx.ERR, "create cache error : ", err)
end

local function set(key, value, ttlInSeconds)
    cache:set(key, value, ttlInSeconds)
end

local function get(key)
    return cache:get(key)
end

local _M = {
  set = set,
  get = get
}

return _M

ここでは,モジュールの特性を用いて,ワークごとにcacheインスタンスを1回だけ初期化することを実現した.2、test_lrucache.lua
local mycache = require("mycache")  
local count = mycache.get("count") or 0  
count = count + 1  
mycache.set("count", count, 10 * 60 * 60) --10    
ngx.say(mycache.get("count"))           

アクセス量統計などの実装は可能ですが、Workerプロセスあたりのみです.3、example.confプロファイル
     location ~ /lua_lrucache {
        default_type 'text/html';
        lua_code_cache on;
        content_by_lua_file /usr/example/lua/test_lrucache.lua;
     }

アクセスhttp://192.168.1.2/lua_lrucacheテスト.
詳細については、https://github.com/openresty/lua-resty-lrucache.
文字列処理
Lua 5.3以前は文字操作に関する関数を提供していなかった.例えば、文字列の切り取り、置換などはすべてバイト単位で操作された.実際に使用するとき、特に中国語を含むシーンでは、明らかにニーズを満たすことができません.Lua 5.3でも基本的なUTF-8操作のみが提供される.
Lua UTF-8ライブラリ
https://github.com/starwing/luautf8
LuaRocksインストール
    #    git     
    apt-get install git  
    luarocks install utf8  
    cp /usr/local/lib/lua/5.1/utf8.so  /usr/example/lualib/

ソースコードのインストール
wget https://github.com/starwing/luautf8/archive/master.zip
unzip master.zip
cd luautf8-master/
gcc -O2 -fPIC -I/usr/include/lua5.1 -c utf8.c -o utf8.o -I/usr/include
gcc -shared -o utf8.so -L/usr/local/lib utf8.o -L/usr/lib

1、test_utf8.lua
  local utf8 = require("utf8")  
    local str = "abc  "  
    ngx.say("len : ", utf8.len(str), "
"
) ngx.say("sub : ", utf8.sub(str, 1, 4))

ファイル符号化はUTF 8でなければなりません.ここでは、最も一般的な文字列長計算と文字列切り取りを実現します.2、example.confプロファイル
    location ~ /lua_utf8 {  
       default_type 'text/html';  
       lua_code_cache on;  
       content_by_lua_file /usr/example/lua/test_utf8.lua;  
    }  

3、訪問http://192.168.1.2/lua_utf8テストは以下の結果を得た.
len:5 sub:abc中
文字列はunicode符号化に変換されます.
local bit = require("bit")
local bit_band = bit.band
local bit_bor = bit.bor
local bit_lshift = bit.lshift
local string_format = string.format
local string_byte = string.byte
local table_concat = table.concat

local function utf8_to_unicode(str)
    if not str or str == "" or str == ngx.null then
        return nil
    end
    local res, seq, val = {}, 0, nil
    for i = 1, #str do
        local c = string_byte(str, i)
        if seq == 0 then
            if val then
                res[#res + 1] = string_format("%04x", val)
            end

           seq = c < 0x80 and 1 or c < 0xE0 and 2 or c < 0xF0 and 3 or
                              c < 0xF8 and 4 or --c < 0xFC and 5 or c < 0xFE and 6 or
                              0
            if seq == 0 then
                ngx.log(ngx.ERR, 'invalid UTF-8 character sequence' .. ",,," .. tostring(str))
                return str
            end

            val = bit_band(c, 2 ^ (8 - seq) - 1)
        else
            val = bit_bor(bit_lshift(val, 6), bit_band(c, 0x3F))
        end
        seq = seq - 1
    end
    if val then
        res[#res + 1] = string_format("%04x", val)
    end
    if #res == 0 then
        return str
    end
    return "\\u" .. table_concat(res, "\\u")
end

ngx.say("utf8 to unicode : ", utf8_to_unicode("abc  "), "
"
)

上記の方法でutf 8 to unicode:61u 4 e 2 du 6587が出力されます.
これで基本的な文字列操作が完了し、他のluautf 8モジュールのAPIやLuaAPIも参照できます.
http://cloudwu.github.io/lua53doc/manual.html#6.4
http://cloudwu.github.io/lua53doc/manual.html#6.5
また、GBKの操作は、先にUTF-8に変換し、最後にGBKに変換すればよい.