Luaライブラリ 要注意点 ~入出力ライブラリ~†
printは最後に改行が付く、io.writeは改行が付かない。†
両方ともリストを引き受けるが、
print(リスト)はタブで連結し、最後は改行を付加。
''printは常に標準出力。
io.write(リスト)は純粋に連結するのみ。
io.writeは現在割り当てられている出力ハンドルが対象。切り替え可能。
(ファイルor標準出力or標準エラーなど、とにかく現在割り当てられているハンドル)
io.read (···)†
io.input():read(···) と同等。
引数 説明
"*all" ファイル全体を読み込みます。
"*line" 次の行を読み込みます。
"*number" 数値を読み込みます。
<num> 最大で<num>文字の文字列を読み込みます。
効率の良い読み込みと出力†
Luaにおいて、最も効率が良いのは、全部を読み込んで、処理して、出力する というもの。
t = io.read("*all") --> 一気に読み込む
t = string.gsub(t, …) --> 何か処理
io.write(t) --> 出力
Luaのデフォルトのファイル読み込み単位は「行」†
次にio.read(*line)も良くある。*lineと指定しなくともread()のデフォルトはこの*lineである。
読み込むのは一行ずつだが、最後の改行はtrimされる。
一番最後に読み込むものが無くなれば、nilを返す。
for count = 1, math.huge do -- 無限ループ
local line = io.read()
if line == nil then break end
io.write(string.format("%6d ", count), line, "\n")
end
ただし、io.lines()イテレータを使用する方が自然である。
local lines = {}
for line in io.lines() do
lines[#lines+1] = line
end
table.sort(lines)
for _, l in ipairs(lines) do
io.write(l, "\n")
end
io.read("*number")†
io.read("*number") は数値入力を受け付ける。
前に空白系の文字があったら無視される。
一行に複数の数値が入っていることが期待される場合、その個数分だけ"*number"を記載すれば良い。
data部
6.0 -3.23 15e12
4.3 234 1000001
io.read("*number", "*number", "*number")
while true do
local n1, n2, n3 = io.read("*number", "*number", "*number")
if not n1 then break end --真ではない。nil or false
print(math.max(n1,n2,n3))
end
C言語のfopen相当の制御†
C言語のfopen相当の制御をするなら
io.open("filename", "r")
が利用可能。
io.open (filename [, mode])†
文字列 mode で指定したモードでファイルを開きます。
新しいファイルハンドルを返します。
エラーの場合は第1返り値がnil、第2返り値がおよびエラーメッセージ、第3返り値がエラー番号等を返します。
mode 文字列は以下のいずれかを指定できます。
"r" 読み込みモード (デフォルト)。
"w" 書き込みモード。
"a" 追記モード。
"r+" 更新モード。 以前のデータは維持されます。
"w+" 更新モード。 以前のデータは消去されます。
"a+" 追記更新モード。 以前のデータは維持され、 ファイルの最後にのみ書き込みができます。
mode 文字列の最後に 'b' を指定することもできます。Win系ではバイナリモードとして必須。
print(io.open("non-exist-file", "r")
--> nil non-exist-file: No such file or directry 2
local f = assert(io.open(filename, "r"))
local t = f:read("*all")
f:close()
定義済のファイルディスクリプタ†
io.stdin 標準入力ストリーム
io.stdout 標準出力ストリーム
io.stderr 標準エラーストリーム
例えば、
io.stderr:write("message")
などで標準エラーストリームにメッセージを送ることが可能。
io.input() io.output()†
引数を付けずにio.input()を呼び出すと、現在の入力ファイルのファイルハンドルを得ることが出来る。
io.input(handle)のような形で引数を渡すと、ハンドルを設定可能。
io.output(), io.output(handle)も同様の仕様である。
local temp = io.input()
io.input("newinput")
--新しい入力ファイルで仕事を行う--
io.input():close() -- ファイルハンドルなのでf:close() などということ。
io.input(temp) -- 以前のファイルハンドルへと設定を復元
バイナリモード†
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())
file:seek ([whence [, offset]])†
offset で指定した位置に文字列 whence で指定した基準を足した位置にファイルの位置を設定し、
先頭から数えたファイルの位置を取得します。 whence は以下のいずれかです。
"set" 基準は位置 0 (ファイルの先頭) です。
"cur" 基準は現在の位置です。
"end" 基準はファイルの終わりです。
成功した場合は、最終的なファイル位置をファイルの先頭から数えたバイト数で返します。
失敗した場合は、nil およびエラーを説明する文字列を返します。
whence のデフォルト値は "cur" で、 offset は 0 です。
そのため、 file:seek() は現在位置を変更せずに現在位置を返し、
file:seek("set") は位置をファイルの先頭に設定し (て 0 を返し)、
file:seek("end") は位置をファイルの終わりに設定してそのファイルのサイズを返します。