ファイル操作
perlでfile.txtというファイルを開くときはopenという関数を使って、
open(FILE, 'file.txt') or die "$!";
のようにすれば良いみたい。開くことができなかったときはエラーメッセージを出して
終了するようにしている。
openの最初の引数はファイルハンドルでファイルを開いた後の操作は
ファイルハンドルを通じて行うみたい。
pythonでもやはりopen関数を使って、
f = open("file.txt", "r")
とすれば良いみたい。第二引数のrは読み込み専用で開くということ。
pythonのopen関数はファイルオブジェクトを返すので、
ここではfに代入している。
開いた後の操作はこのファイルオブジェクトのメソッドを使って行うようなので、
perlのファイルハンドルに当たると考えればよいのかな。
ファイルを閉じるときはperlではclose関数にファイルハンドルを指定して、
close(FILE);
とすればよいみたい。
pythonではファイルオブジェクトのcloseメソッドで
f.close()
のようにすれば良いみたい。
openとcloseの間でファイルの処理を行うことになるわけで、
例えばpythonで
f.read()
とすると、ファイル全体を1つの文字列で返してくる。
ファイルをテキストファイルではなく、バイナリファイルとして扱うときは
perlの場合はbinmode関数を呼び出す必要があるみたい。
引数にはファイルハンドルを与えてbinmode(FILE)のように使うみたい。
pythonの場合はopen関数のモードを指定する引数でバイナリモードを指定できて、
バイナリモードで読み込むときは、
f = open("data.bin", "rb")
のようにすれば良いみたい。
csvファイルを扱うときはpythonではcsvモジュールを使うと良いみたい。
例えば以下のような内容のファイル(data.txt)があって、
Hanako, 65, 90, 100, 80, 73 Ichiro, 8, 7, 23, 21, 24 Jiro, 74, 31, 41, 59, 38 Taro, 100, 95, 98, 82, 61 Hiroko, 55, 48, 79, 90, 88 Saburo, 74, 41, 59, 31, 38
各人の数値を合計して名前の隣に表示するスクリプトを以下のように
書いてみた。
import csv csvfile = "data.txt" reader = csv.reader(file(csvfile, "rb")) #csvファイルの読み込みにはcsv.readerオブジェクトを使うみたい。 for row in reader: #rowは各人の名前と数値の文字列を要素として持つリストになる。 score = row[1:] #数値の文字列のみを持つリストをつくる。 sum = 0 int_score_list = [] for i in score: #数値の文字列を数値化してリストにする。 int_score = int(i) int_score_list.append(int_score) for s in int_score_list: #合計値を計算 sum = sum + s print row[0],sum
実行結果は以下の通り。
Hanako 408 Ichiro 83 Jiro 243 Taro 436 Hiroko 360 Saburo 243
次にカレントディレクトリ内のファイルの名前の一覧を表示する
プログラムを書いてみる。
pythonではosモジュールの引数に与えたファイルやディレクトリのリストを返すlistdirという関数を使って、
引数にカレントディレクトリの名前を与えればよいみたい。
カレントディレクトリはやはりosモジュールのgetcwdという関数で取得できるみたいだから、
以下のように書けた。
import os dirname = os.getcwd() files = os.listdir(dirname) for file in files: print file
pathが存在するかどうか調べるときはpythonではosモジュールのexistsという関数を使って、
import os
os.path.exists(path)
とする。pathが存在すればTrueが、存在しなければFalseが返ってくる。
ファイルpathのサイズをバイト数で得るには、
import os
os.path.getsize(path)
とすれば良いみたい。
カレントディレクトリ中の拡張子が.txtのファイルの一覧を取得するには,
該当ファイル名をリストにして返す
globモジュールのglob関数を使うと便利みたいで、
import glob glob.glob("*.txt")
のように使うみたい。
この他、ファイルpathを削除するときはremove関数、ディレクトリpathの削除にはrmdir関数、
ファイル名またはディレクトリ名の変更にはrename関数を以下のように使えばよいみたい。
import os
os.remove(path)
os.rmdir(path)
os.rename(変更前のpath, 変更後のpath)
さて次は問題に取り組んでみる。
mmlog.txtというファイルの内容は以下のようになっている。
No.0010 615 No.0009 602 No.0008 569 No.0007 549 No.0006 535 No.0005 514 No.0004 23 No.0003 19 No.0002 10 No.0001 4 No.0000 1
このファイルを元にNo.が1つ増えるごとに右の数値がどれだけ増加したかを
表示するプログラムを以下のように書いてみた。
f = open("mmlog.txt", "r") #ファイルを読み込みモードで開いて content = f.readlines() #ファイルの各行をリストに読み込む f.close() blist = [] for i in content: s_content = i.split() #ファイルの各行をNo.と数値の部分に分けて busuu = int(s_content[1]) #数値の部分を文字列から数値化する blist.append(busuu) #数値の入ったリストを作成 n = range(0, 10) n.reverse() #9〜0のリストを作成 n2 = range(1, 11) n2.reverse() #10〜1のリストを作成 for y in range(0,10): #出力する表を作成 print "No.%04d => No.%04d: %d" %(n[y], n2[y], blist[y]-blist[y+1])
実行結果は以下の通り。
No.0009 => No.0010: 13 No.0008 => No.0009: 33 No.0007 => No.0008: 20 No.0006 => No.0007: 14 No.0005 => No.0006: 21 No.0004 => No.0005: 491 No.0003 => No.0004: 4 No.0002 => No.0003: 9 No.0001 => No.0002: 6 No.0000 => No.0001: 3
次にカレントディレクトリの拡張子が.txtであるファイルすべてについて、そのファイルが、
・更新されて1日以内(day)
・更新されて1週間以内(week)
・更新されて1週間より多く経過(old)
のいずれかに当てはまるか調べて表示するプログラムを書いてみた。
スクリプトは以下の通り。
import os import glob import time cdir = os.getcwd() #カレントディレクトリを取得 files = glob.glob("*.txt") #カレントディレクトリ内の拡張子が.txtのすべてのファイルを取得 filenames = [os.path.join(cdir,file) for file in files] #該当ファイルの絶対パスを取得 for absfile in filenames: renewtime = os.path.getmtime(absfile) #該当ファイルの最終更新時刻を取得 if renewtime >= time.time() - 60*60*24: print "(day) %s" %absfile.split("\\")[-1] #更新が1日以内のものを表示 elif time.time() - 60*60*24 > renewtime >= time.time() - 60*60*24*7: print "(week) %s" %absfile.split("\\")[-1] #更新が1週間以内のものを表示 else: print "(old) %s" %absfile.split("\\")[-1] #更新が1週間より前のものを表示
実行結果は以下の通り。
(day) data.txt (old) memo.txt (week) mmlog.txt (week) monndai7_4.txt (old) newfile.txt (old) test.txt (old) test2.txt