ファイルへの追記とデータ書き込み
ファイルを開く際、モード文字として'a'(append)を指定すると、ファイルの末尾にデータを追加する追記モードとして動作します。指定されたパスにファイルが存在しない場合、自動的に新規ファイルが作成されます。
# データの追記処理
with open('log_data.txt', 'a', encoding='utf-8') as file_obj:
file_obj.write('処理開始\n')
file_obj.write('システム稼働中\n')
file_obj.write('処理完了\n')
# write()メソッドは文字列を書き込みます。改行が必要な場合は\nを明示的に含めます。
テキストモードとバイナリモードの違い
Pythonのファイル操作には、テキストを扱う「テキストモード(Text Mode)」と、画像や実行ファイルのようなバイト列を扱う「バイナリモード(Binary Mode)」が存在します。
テキストモード('t')はデフォルトの動作です(例: 'r', 'w'は内部的に'rt', 'wt'となります)。このモードでは、データは文字列(str型)として扱われ、encodingパラメータの指定が必須となります。
バイナリモード('b')は、任意のファイル形式を扱うためのモードです(例: 'rb', 'wb')。データはバイト列(bytes型)として扱われ、エンコーディングの指定は不要です。
# バイナリモードでの読み込みと書き込み
with open('source.bin', 'rb') as f:
raw_data = f.read()
# 読み込んだデータはbytes型となるため、そのまま表示するとエスケープシーケンスが見えます
# バイナリデータとして書き込む場合、文字列はencode()で変換する必要があります
with open('output.bin', 'wb') as f:
text_content = "バイナリデータ"
f.write(text_content.encode('utf-8'))
主要なファイル操作メソッド
.read(): ファイルの全内容を一度に読み込みます。.readline(): ファイルから1行だけを読み込みます。.readlines(): ファイルの全内容を読み込み、各行を要素とするリストを返します。.readable(): ファイルが読み取り可能かどうかを判定します。.write(str): 引数の文字列をファイルに書き込みます。.writelines(list): リスト内の文字列要素をまとめて書き込みます。.flush(): バッファに蓄積されたデータを即座にディスクに書き出します(強制保存)。
大容量ファイルの効率的な読み込み
.read()を使用して巨大なファイルを一度に読み込むと、メモリ不足(OOM)を引き起こすリスクがあります。また、一度読み込むとファイルポインタが末尾に移動するため、再度読み込むにはシーク(移動)操作が必要です。
これを解決する一般的なイディオムは、ファイルオブジェクトを直接イテレータとして使用し、行単位で処理することです。
# メモリ効率を考慮した行単位の読み込み
with open('large_dataset.log', 'r', encoding='utf-8') as file_stream:
# forループでファイルオブジェクトを直接回すことで、1行ずつメモリに展開して処理します
for line in file_stream:
process(line) # 各行に対する処理
実践:ファイルベースのユーザー認証システム
以下は、テキストファイルをデータベース代わりに使用した簡易的なユーザー登録およびログインシステムの実装例です。
import os
DB_FILE = 'user_database.txt'
# データベースファイルが存在しない場合は作成
if not os.path.exists(DB_FILE):
with open(DB_FILE, 'w', encoding='utf-8') as f:
pass
def main():
while True:
action = input("機能を選択してください [1:登録, 2:ログイン, その他:終了]: ").strip()
if action == '1':
# --- ユーザー登録 ---
username = input("登録するユーザー名: ").strip()
password = input("パスワード: ").strip()
# ユーザー名の重複チェック
is_duplicate = False
with open(DB_FILE, 'r', encoding='utf-8') as f:
for line in f:
stored_user, _ = line.strip().split('|')
if stored_user == username:
is_duplicate = True
print("エラー: このユーザー名は既に使用されています。")
break
if not is_duplicate:
# 重複がなければファイルに追加
with open(DB_FILE, 'a', encoding='utf-8') as f:
# フォーマット: ユーザー名|パスワード
f.write(f"{username}|{password}\n")
print(f"ユーザー '{username}' の登録が完了しました。")
elif action == '2':
# --- ユーザーログイン ---
login_user = input("ユーザー名: ").strip()
login_pass = input("パスワード: ").strip()
authenticated = False
with open(DB_FILE, 'r', encoding='utf-8') as f:
for line in f:
# 改行文字を除去し、パイプで分割
parts = line.strip().split('|')
if len(parts) == 2:
stored_user, stored_pass = parts
if stored_user == login_user and stored_pass == login_pass:
authenticated = True
break
if authenticated:
print("ログイン成功!ようこそ。")
else:
print("ログイン失敗:ユーザー名またはパスワードが間違っています。")
else:
print("システムを終了します。")
break
if __name__ == "__main__":
main()