1. ホーム
  2. スクリプト・コラム
  3. ルア

Luaチュートリアル(VIII)。データの永続化

2022-02-13 09:42:35

1. データファイル

    Luaのテーブル構成要素を利用して、以下のようなLuaプログラムにとって非常に便利で分かりやすい方法で、ファイル内のデータをテーブルが構成し初期化するコードとするファイル形式を定義することができます。

コピーコード コードは以下の通りです。

    Entry { "Stephen Liu", "Male", "Programmer", "BS" }
    Entry { "Jerry Tian", "Male", "Programmer", "BS" }

    なお、Entry{<code>}はEntry({<code>})と同等で、上記のデータエントリについては、適切なEntry関数を定義できれば、このデータをLuaコードの一部にすることが可能です。以下のコードとそのコメントをご覧ください。
コピーコード コードは以下の通りです。

local count = 0
-- The Entry function is pre-defined here so that when the data code in the dofile is executed, it can find a match for that function.
function Entry() count = count + 1 end
dofile("d:/lua_data.conf")
print("number of entries: " . count)

-- The output is.
--number of entries: 2

上記のデータファイル形式とは対照的に、より明確な "自己記述型データ" 形式を定義することができます。これは、データの各項目に、それが何を意味するのかを示す短い説明を添えたものです。このフォーマットでは、将来的にデータ項目が変更されても、最小限の変更で後方互換性を維持することができます。以下のデータ形式と関連するコードをご覧ください。

コピーコード コードは以下の通りです。

    Entry { name = "Stephen Liu", gender = "Male", job = "Programmer", education = "BS" }
    Entry { name = "Jerry Tian", gender = "Male", job = "Programmer", education = "BS" }

コピーコード コードは以下の通りです。

local personInfo = {}
function Entry(b)
    -- Here the name field value of table object b is used as the key information of personInfo.
    if b.name then
        personInfo[b.name] = true
    end
end

dofile("d:/lua_data.conf")
for name in pairs(personInfo) do
    print(name)
end

-- The output is.
--Jerry Tian
--Stephen Liu

Entry関数はコールバック関数として動作し、doファイルの実行時にデータファイルの各エントリに対して呼び出されます。

    Luaは動作が速いだけでなく、コンパイルも速い。これは、Luaが当初からデータ記述をLuaの主要な用途の1つとして設計されていたことが大きく影響しています。
    2. シリアライゼーション。

    JavaやC#の開発経験がある方なら、この言葉はよくご存知だと思います。データオブジェクトをIOでファイルやネットワークに出力する前にバイトのストリームに変換し、そのデータを読み込んだときに元のオブジェクトと同じ値を持つ新しいオブジェクトに再構築することです。また、シリアル化されたデータのフォーマットとして、実行可能なLuaコードの一部を使用することも可能です。例えば、varname = <expr> とすると、 <expr> は変数varnameを計算する式を表しています。次のコード例は、非周期表をシリアライズするために使用される。

コピーコード コードは以下の通りです。

 function serialize(o)
    if type(o) == "number" then
        io.write(o)
    elseif type(o) == "string" then
        The "%q" parameter of the --string.format function escapes the metacharacters in the string.
        io.write(string.format("%q",o))
    elseif type(o) == "table" then
        io.write("{\n")
        -- Iterate over the elements of the table while recursively writing the value of each field.
        -- As you can see, this simple example can support nested tables.
        for k,v in pairs(o) do
            -- This is done to prevent k from containing illegal Lua identifiers.
            io.write(" ["); serialize(k); io.write("] = ")
            serialize(v)
            io.write(",\n")
        end
        io.write("}\n")
    else
        error("can't serialize a " . type(o))
    end
end