LuaのファイルIOを触る機会があったので、サンプルコードを付けて少しまとめました。
(この記事で扱うのは、追加ライブラリ等を使わずに読み書きする方法のみです)
ファイル読み込み
ファイル全体を1度に読み込む
-- ファイルを読み込みモード('r')で開く
local f = io.open('myInputFile.txt', 'r')
-- ファイル全体を読み込む
local content = f:read('a')
-- ファイルを閉じる
f:close()
※古いバージョンのLuaだとf:read()に’*a’と指定する必要があるかもしれないのでご注意ください。
1行ずつ読み込む
-- ファイルを読み込みモード('r')で開く
local f = io.open('myInputFile.txt', 'r')
-- 開いたファイルの先頭から一行ずつ読み込むループ
for line in f:lines() do
-- ここに1行ごとの処理を書く
print(line)
end
-- ファイルを閉じる
f:close()
ファイル書き込み
-- 書き込む内容(stringまたはnumberを指定可能)
local content = 'Hello World!'
-- 出力先のファイルを書き込みモード('w')で開く
local f = io.open('myOutputFile.txt', 'w')
-- ファイルに書き込む
f:write(content)
-- ファイルを閉じる
f:close()
出力先に指定したファイルの扱いは以下です。
- 存在しないファイルを指定した場合→新規作成
- 途中のディレクトリが存在しない場合はディレクトリも新規作成
- 存在するファイルを指定した場合→上書き
末尾への追記等、他のモードについては後述の表をご参照ください。
その他
エラー処理
上記で紹介した関数はいずれもエラー時にnil(fail)/エラーメッセージ/エラーコードを返します。
例えばio.open()のエラーをハンドリングしたい場合は以下のように記載します。
local f, errorMessage, errorCode = io.open('/hoge/myOutputFile2.txt', 'r')
if f == nil then
-- ファイルオープンに失敗した場合の処理をここに書く
print(myErrorMessage .. ', errno=' .. myErrorCode)
-- 例えば存在しないファイルを指定した場合だと以下のようなエラーメッセージとなる
-- '/hoge/myOutputFile2.txt: No such file or directory, errno=2'
end
エラーメッセージ、エラーコードが不要な場合は以下のように書いてもOKです。
local f = io.open('/hoge/myOutputFile2.txt', 'r')
if f == nil then
-- ファイルオープンに失敗した場合の処理をここに書く
print('Failed to open file.')
end
ファイル操作を行う毎にエラー処理を書くのは少し冗長な気がしますが、少なくともio.open()は権限やパス誤り等で失敗することが十分にあり得るので書いておいた方が良いです。
io.open()に指定できるモード一覧
サンプルコードで使用した’r’と’w’以外は余り使わないですが、一応Luaでは以下が使用可能です
r | ・読み込みモード ・ファイル先頭から読み込む |
w | ・書き込みモード ・存在するファイルを指定した場合はopen時に元データは削除される |
a | ・書き込みモード ・ファイル末尾に追記する |
r+ | ・読み込み/書き込みモード ・ファイル先頭から読み込み/書き込みが可能 |
w+ | ・読み込み/書き込みモード ・存在するファイルを指定した場合はopen時に元データ削除 |
a+ | ・読み込み/書き込みモード ・書き込みはファイル末尾にのみ可能 |
バイナリファイルの読み込み/書き込み
バイナリファイルの読み込み/書き込みを行う場合は、io.open()で指定するモードの後ろに’b’を記載します。
-- バイナリファイルを読み込みモード('rb')で開く
local f = io.open('myInputFile.pcap', 'rb')
-- バイナリファイルを書き込みモード('wb')で開く
local f = io.open('myInputFile.pcap', 'wb')
closeを書き忘れるとどうなるのか?
LuaではファイルハンドラがGCされたタイミングで自動的に閉じられます。
しかし、GCのタイミングはコード側で制御できないので明示的にclose()を行うべきです。
環境にもよりますが、同時に開けるファイル数には上限があるため、例えばループなどでclose()を行わずにファイルを繰り返し開くと上限に到達することもあります。
最悪のケースだと他のプログラムやOSの機能にも影響が出ます。
参考
Lua 5.4 Reference Manual
コメント