風柳メモ

ソフトウェア・プログラミング関連の覚書が中心

【覚書】ファイルを1行/一定サイズ毎に処理する際のシンプルな記述

テキストファイルを 1 行毎に処理

これまで

fp = open('sample.txt', 'r')
#{
line = fp.readline() # → これと…
while line:
  proc(line) # 1行毎の処理
  fp.readline() # → これとが冗長
#}
fp.close()

のように readline() が2回出てくる冗長な書き方をしていたが、実はファイルオブジェクトはイテレータなので、#{〜#}の〜部分は、

for line in fp:
  proc(line) # 1行毎の処理

のようにシンプルに書ける。

バイナリファイルを一定バイト数毎に処理

イテレータとして見た場合、ファイルオブジェクトの持つ next()(for文で暗黙的にコールされる)は、先の例のように行単位で処理される。

これを行単位以外、例えば、一定サイズを読み込む毎に処理させたい場合、イテレータを利用して、

bufsize = 16 # 1回あたりの読み込みサイズ(例は16バイト毎に処理する場合)
fp = open('sample.bin', 'rb')
for buf in iter(lambda:fp.read(bufsize),''):
  proc(buf) # 一定サイズ毎の処理
fp.close()

のように書ける。
iter(lambda:fp.read(bufsize),'')にて、bufsizeずつ読み込んだ結果を返すイテレータを作成している。
iter()の第1引数は<iterator>.nextでコールされる関数、第2引数は終了条件で、第1引数で指定した関数が返す結果が第2引数と等しければ終了する。