最初の版はLua 5.0向けに執筆されました。後のバージョンでも大部分は関連していますが、違いがいくつかあります。
第4版はLua 5.3を対象としており、Amazonや他の書店で購入できます。
この本を購入することで、Luaプロジェクトの支援にも役立ちます。


21.2.2 – バイナリファイル

単純モデル関数io.inputio.outputは、常にファイルをテキストモード(既定値)で開きます。Unixでは、バイナリファイルとテキストファイルの区別はありません。しかし、Windowsを代表とする一部のシステムでは、バイナリファイルは特殊なフラグで開かなければなりません。そのようなバイナリファイルを処理するには、モード文字列に文字`b´を使用してio.openを使用する必要があります。

Luaのバイナリデータはテキストと同様に処理されます。Luaの文字列には任意のバイトを含めることができ、ライブラリのほとんどすべての関数が任意のバイトを処理できます。(パターンにゼロバイトが含まれていない限り、バイナリデータのパターンマッチングを行うこともできます。ゼロバイトを照合するには、代わりにクラス%zを使用できます。)

通常、バイナリデータは、ファイルを全体読み取る*allパターン、またはnバイトを読み取るパターンnを使用して読み取ります。簡単な例として、次のプログラムはテキストファイルをDOS形式からUnix形式に変換します(つまり、キャリッジリターン-改行のシーケンスを改行に変換します)。標準I/Oファイル(stdin/stdout)はテキストモードで開かれるため、使用しません。代わりに、入力ファイルと出力ファイルの名前はプログラムへの引数として渡されると想定します。

    local inp = assert(io.open(arg[1], "rb"))
    local out = assert(io.open(arg[2], "wb"))
    
    local data = inp:read("*all")
    data = string.gsub(data, "\r\n", "\n")
    out:write(data)
    
    assert(out:close())
次のコマンドラインでこのプログラムを呼び出すことができます
    > lua prog.lua file.dos file.unix

別の例として、次のプログラムはバイナリファイルにあるすべての文字列を出力します。このプログラムでは、文字列は6文字以上の有効文字のゼロ終端シーケンスであり、有効文字とはパターンvalidcharsで受け入れられる任意の文字であると想定しています。私たちの例では、英数字、句読点、スペース文字で構成されています。連結とstring.repを使用して、6文字以上のvalidcharsのすべてのシーケンスを取得するパターンを作成します。パターンの末尾の%zは、文字列の末尾にあるゼロバイトと一致します。

    local f = assert(io.open(arg[1], "rb"))
    local data = f:read("*all")
    local validchars = "[%w%p%s]"
    local pattern = string.rep(validchars, 6) .. "+%z"
    for w in string.gfind(data, pattern) do
      print(w)
    end

最後の例として、次のプログラムはバイナリファイルのダンプを作成します。ここでも、最初のプログラム引数は入力ファイル名であり、出力は標準出力に出力されます。このプログラムは、ファイルを10バイトのチャンクで読み取ります。各チャンクについて、各バイトの16進表現を書き込み、次にチャンクをテキストとして書き込み、制御文字をドットに変更します。

    local f = assert(io.open(arg[1], "rb"))
    local block = 10
    while true do
      local bytes = f:read(block)
      if not bytes then break end
      for b in string.gfind(bytes, ".") do
        io.write(string.format("%02X ", string.byte(b)))
      end
      io.write(string.rep("   ", block - string.len(bytes) + 1))
      io.write(string.gsub(bytes, "%c", "."), "\n")
    end
そのプログラムをvipという名前のファイルに保存するとします。次の呼び出しでプログラムをそれ自体に適用すると
    prompt> lua vip vip
出力は(Unixマシンでは)次のようになります
    6C 6F 63 61 6C 20 66 20 3D 20    local f = 
    61 73 73 65 72 74 28 69 6F 2E    assert(io.
    6F 70 65 6E 28 61 72 67 5B 31    open(arg[1
    5D 2C 20 22 72 62 22 29 29 0A    ], "rb")).
               ...
    22 25 63 22 2C 20 22 2E 22 29    "%c", ".")
    2C 20 22 5C 6E 22 29 0A 65 6E    , "\n").en
    64 0A                            d.