この第1版は Lua 5.0 向けに書かれています。後のバージョンにもほぼ当てはまりますが、いくつかの違いがあります。
第4版は Lua 5.3 を対象としており、Amazon やその他の書店で入手できます。
本書を購入することで、Lua プロジェクトの支援にもなります。
![]() |
Luaプログラミング | ![]() |
第III部 標準ライブラリ 第21章 入出力ライブラリ |
シンプルなモデルは、2つのカレントファイルに対してすべての操作を行います。ライブラリは、カレント入力ファイルをプロセスの標準入力(stdin
)として、カレント出力ファイルをプロセスの標準出力(stdout
)として初期化します。したがって、io.read()
のようなものを実行すると、標準入力から1行読み込みます。
これらのカレントファイルは、io.input
関数と io.output
関数で変更できます。 io.input(filename)
のような呼び出しは、指定されたファイルを読み込みモードで開き、カレント入力ファイルとして設定します。この時点から、io.input
が再度呼び出されるまで、すべての入力はこのファイルから行われます。 io.output
は出力に対して同様の動作をします。エラーが発生した場合、両方の関数はエラーを発生させます。エラーを直接処理したい場合は、完全モデルの io.open
を使用する必要があります。
write
は read
よりも単純なので、まずこちらを見てみましょう。 io.write
関数は、任意の数の文字列引数を受け取り、カレント出力ファイルに書き込みます。数値は通常の変換規則に従って文字列に変換されます。この変換を完全に制御するには、string
ライブラリの format
関数を使用する必要があります。
> io.write("sin (3) = ", math.sin(3), "\n") --> sin (3) = 0.1411200080598672 > io.write(string.format("sin (3) = %.4f\n", math.sin(3))) --> sin (3) = 0.1411
io.write(a..b..c)
のようなコードは避けてください。 io.write(a,b,c)
の呼び出しは、連結を避けるため、より少ないリソースで同じ効果を実現します。原則として、手軽なプログラムやデバッグには print
を使用し、出力内容を完全に制御する必要がある場合は write
を使用する必要があります。
> print("hello", "Lua"); print("Hi") --> hello Lua --> Hi > io.write("hello", "Lua"); io.write("Hi", "\n") --> helloLuaHi
print
とは異なり、write
はタブや改行などの余分な文字を出力に追加しません。さらに、write
はカレント出力ファイルを使用しますが、print
は常に標準出力を使用します。最後に、print
は引数に自動的に tostring
を適用するため、テーブル、関数、nil も表示できます。read
関数は、カレント入力ファイルから文字列を読み込みます。引数によって、何が読み込まれるかが制御されます。
"*all" | ファイル全体を読み込みます |
"*line" | 次の行を読み込みます |
"*number" | 数値を読み込みます |
num | 最大 *num* 文字の文字列を読み込みます |
io.read("*all")
の呼び出しは、現在の位置から開始して、カレント入力ファイル全体を読み込みます。ファイルの末尾にある場合、またはファイルが空の場合、呼び出しは空の文字列を返します。
Lua は長い文字列を効率的に処理するため、Lua でフィルタを記述する簡単な手法は、ファイル全体を文字列に読み込み、文字列に対して処理を行い(通常は gsub
を使用)、文字列を出力に書き込むことです。
t = io.read("*all") -- read the whole file t = string.gsub(t, ...) -- do the job io.write(t) -- write the file例として、次のコードは、MIME の *quoted-printable* エンコーディングを使用してファイルの内容をエンコードする完全なプログラムです。このエンコーディングでは、ASCII 以外の文字は
=
*XX* としてエンコードされます。ここで、*XX* は16進数での文字の数値コードです。エンコーディングの整合性を保つために、「=
」文字もエンコードする必要があります。 gsub
で使用されるパターンは、128 から 255 までのコードを持つすべての文字と、等号をキャプチャします。t = io.read("*all") t = string.gsub(t, "([\128-\255=])", function (c) return string.format("=%02X", string.byte(c)) end) io.write(t)Pentium 333MHz では、このプログラムは 200K 文字のファイルを変換するのに 0.2 秒かかります。
io.read("*line")
の呼び出しは、カレント入力ファイルから次の行を改行文字なしで返します。ファイルの末尾に達すると、呼び出しは nil を返します(返す次の行がないため)。このパターンは read
のデフォルトであるため、io.read()
は io.read("*line")
と同じ効果があります。通常、このパターンは、アルゴリズムがファイルを行ごとに自然に処理する場合にのみ使用します。そうでない場合は、後で説明するように、*all
を使用してファイル全体を一度に読み込むか、ブロック単位で読み込むことをお勧めします。このパターンの使用例として、次のプログラムはカレント入力をカレント出力にコピーし、各行に番号を付けます。
local count = 1 while true do local line = io.read() if line == nil then break end io.write(string.format("%6d ", count), line, "\n") count = count + 1 endただし、ファイル全体を行ごとに反復処理するには、
io.lines
イテレータを使用する方が適切です。たとえば、ファイルの行をソートする完全なプログラムは次のように記述できます。local lines = {} -- read the lines in table 'lines' for line in io.lines() do table.insert(lines, line) end -- sort table.sort(lines) -- write all the lines for i, l in ipairs(lines) do io.write(l, "\n") endこのプログラムは、4.5 MB(32K 行)のファイルを 1.8 秒でソートします(Pentium 333MHz)。C で記述され高度に最適化されたシステムの
sort
プログラムでは 0.6 秒かかります。io.read("*number")
の呼び出しは、カレント入力ファイルから数値を読み込みます。これは、read
が文字列ではなく数値を返す唯一のケースです。ファイルから多くの数値を読み取る必要がある場合、中間文字列がないことでパフォーマンスが大幅に向上する可能性があります。 *number
オプションは、数値の前にあるスペースをスキップし、-3
、+5.2
、1000
、-3.4e-23
などの数値形式を受け入れます。現在のファイル位置に数値が見つからない場合(形式が正しくないか、ファイルの末尾のため)、nil を返します。
read
は複数のオプションを指定して呼び出すことができます。引数ごとに、関数はそれぞれの結果を返します。1行あたり3つの数値を含むファイルがあるとします。
6.0 -3.23 15e12 4.3 234 1000001 ...ここで、各行の最大値を出力したいとします。
read
を1回呼び出すだけで、3つの数値すべてを読み取ることができます。while true do local n1, n2, n3 = io.read("*number", "*number", "*number") if not n1 then break end print(math.max(n1, n2, n3)) endいずれの場合も、
io.read
からオプション "*all"
を使用してファイル全体を読み込み、次に gfind
を使用して分割するという代替案を常に検討する必要があります。local pat = "(%S+)%s+(%S+)%s+(%S+)%s+" for n1, n2, n3 in string.gfind(io.read("*all"), pat) do print(math.max(n1, n2, n3)) end
基本的な読み取りパターンの他に、数値 *n* を引数として read
を呼び出すことができます。この場合、read
は入力ファイルから *n* 文字を読み取ろうとします。文字を読み取れない場合(ファイルの末尾)、read
は nil を返します。それ以外の場合、最大 *n* 文字の文字列を返します。この読み取りパターンの例として、次のプログラムは、stdin
から stdout
にファイルをコピーする効率的な方法です(もちろん Lua で)。
local size = 2^13 -- good buffer size (8K) while true do local block = io.read(size) if not block then break end io.write(block) end
特別な場合として、io.read(0)
はファイルの末尾のテストとして機能します。読み取るべきものが残っている場合は空の文字列を返し、そうでない場合は nil を返します。
Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved.(著作権 © 2003–2004 Roberto Ierusalimschy. 無断転載禁止。) | ![]() |