プログラミングを学んでいると、「モード指示子」という言葉に出会うことがあります。
特にファイル操作のコードを書くとき、こんな記述を見たことはありませんか?
f = open("data.txt", "r")
この"r"がモード指示子です!
「モード指示子?難しそう…」と感じるかもしれませんが、実はたった数文字の記号で、ファイルをどう扱うかを指定しているだけなんです。
今回は、モード指示子の基本から、プログラミング言語別の使い方、実践的な例まで、初心者の方にも分かりやすく徹底解説していきますね!
モード指示子の基本概念

モード指示子とは何か
モード指示子(Mode Specifier)とは、プログラムがファイルやリソースをどのように扱うかを指定する文字列や記号のことです。
簡単に言うと:
ファイルを「読むだけ」なのか「書き込む」のか「追記する」のかを指示する記号
これだけです!
なぜモード指示子が必要なのか
ファイルを開くとき、プログラムは以下を判断する必要があります:
判断1: 読み取り?書き込み?
- データを読むだけなのか
- 新しいデータを書くのか
- 既存のデータに追加するのか
判断2: テキスト?バイナリ?
- 普通の文字データなのか
- 画像や動画などのバイナリデータなのか
判断3: ファイルがない場合は?
- エラーにするのか
- 新しく作成するのか
これらをモード指示子で一度に伝えるんです。
身近な例で理解しよう
ノートを使う場面を想像してみてください。
「読むだけモード」(‘r’):
- 図書館で本を読む
- ページをめくって内容を確認
- 書き込みは禁止
「書き込みモード」(‘w’):
- 新しいノートに日記を書く
- 前の内容は消えてもOK
- 最初から書き始める
「追記モード」(‘a’):
- 既存のノートの続きに書く
- 前の内容は残したまま
- 最後のページから続ける
ファイル操作も同じ考え方なんです。
ファイル操作のモード指示子
最もよく使われるのが、ファイル操作のモード指示子です。
基本的なモード一覧
読み取りモード:
- ‘r’ (read): 読み取り専用で開く
- ‘rb’ (read binary): バイナリ読み取り
書き込みモード:
- ‘w’ (write): 書き込み用に開く(既存内容を削除)
- ‘wb’ (write binary): バイナリ書き込み
追記モード:
- ‘a’ (append): 追記用に開く(既存内容を保持)
- ‘ab’ (append binary): バイナリ追記
読み書き両用モード:
- ‘r+’: 読み書き可能(ファイルが必要)
- ‘w+’: 読み書き可能(ファイルを新規作成または上書き)
- ‘a+’: 読み書き可能(追記、ファイルがなければ作成)
各モードの詳細解説
それぞれのモードを詳しく見ていきましょう。
‘r’ モード(読み取り専用)
最も基本的なモードです。
特徴:
- ファイルの内容を読むだけ
- 書き込みはできない
- ファイルが存在しないとエラー
- デフォルトのモード(指定しないとこれになる)
使い所:
- 設定ファイルを読み込む
- ログファイルを確認する
- データファイルを解析する
‘w’ モード(書き込み)
新しくデータを書き込むモードです。
特徴:
- ファイルに書き込める
- 既存の内容は削除される(注意!)
- ファイルがなければ新規作成
- 読み取りはできない
使い所:
- 新しいログファイルを作る
- レポートを出力する
- 一から作り直すファイル
注意: 既存ファイルを指定すると中身が消えるので注意してください!
‘a’ モード(追記)
既存の内容を保ったまま追加するモードです。
特徴:
- ファイルの最後に追記される
- 既存の内容は保持される
- ファイルがなければ新規作成
- 読み取りはできない
使い所:
- ログファイルに追記
- 日記帳に新しいエントリーを追加
- データを蓄積していく用途
‘r+’ モード(読み書き両用)
読み取りも書き込みもできるモードです。
特徴:
- 読み取りも書き込みも可能
- ファイルが存在する必要がある
- 既存の内容は削除されない
- ファイルポインタは先頭から
使い所:
- ファイルの一部を読んで修正
- データベースファイルの更新
注意: 書き込み位置を意識する必要があります。
‘w+’ モード(読み書き、上書き)
新規作成して読み書きするモードです。
特徴:
- 読み書き両方可能
- 既存の内容は削除される
- ファイルがなければ作成
使い所:
- 一時ファイルの作成と読み書き
- テストデータの生成
‘a+’ モード(読み書き、追記)
追記しながら読み取りもできるモードです。
特徴:
- 読み書き両方可能
- 書き込みは常に末尾に追加
- 既存の内容は保持
- ファイルがなければ作成
使い所:
- ログの追記と確認を同時に行う
バイナリモードとテキストモード
モード指示子にbが付くとバイナリモードになります。
テキストモード(’r’, ‘w’, ‘a’ など):
- 文字データとして扱う
- 改行コードが自動変換される(WindowsとUnixの違いを吸収)
- 文字エンコーディングが適用される
例: テキストファイル、CSVファイル、JSONファイル
バイナリモード(’rb’, ‘wb’, ‘ab’ など):
- バイト列として扱う
- データはそのまま(変換なし)
- 文字エンコーディングは関係ない
例: 画像ファイル、動画ファイル、実行ファイル
どちらを使う?
- 文字が書いてあるファイル → テキストモード
- それ以外(画像、音声、動画など) → バイナリモード
迷ったらバイナリモードが安全です(データが壊れない)。
プログラミング言語別の使い方
各言語での具体的な使い方を見ていきましょう。
Python でのモード指示子
Pythonは非常に直感的です。
基本的な読み取り:
# テキストファイルを読む
with open("data.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content)
# 1行ずつ読む
with open("data.txt", "r", encoding="utf-8") as f:
for line in f:
print(line.strip())
書き込み:
# 新規作成または上書き
with open("output.txt", "w", encoding="utf-8") as f:
f.write("こんにちは\n")
f.write("世界\n")
追記:
# 既存ファイルに追加
with open("log.txt", "a", encoding="utf-8") as f:
f.write("新しいログエントリー\n")
バイナリファイルの読み書き:
# 画像ファイルをコピー
with open("photo.jpg", "rb") as source:
with open("photo_copy.jpg", "wb") as dest:
dest.write(source.read())
読み書き両用:
# ファイルを読んで、最後に追記
with open("data.txt", "r+", encoding="utf-8") as f:
content = f.read()
print("現在の内容:", content)
f.write("\n新しい行を追加")
Pythonのポイント:
with文を使うとファイルが自動的に閉じられるencodingでエンコーディングを指定(日本語なら”utf-8″推奨)
C言語でのモード指示子
C言語のfopen関数でもモード指示子を使います。
基本的な使い方:
#include <stdio.h>
int main() {
FILE *fp;
// 読み取りモード
fp = fopen("data.txt", "r");
if (fp == NULL) {
printf("ファイルを開けません\n");
return 1;
}
char buffer[256];
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("%s", buffer);
}
fclose(fp);
return 0;
}
書き込み:
FILE *fp = fopen("output.txt", "w");
if (fp != NULL) {
fprintf(fp, "こんにちは世界\n");
fclose(fp);
}
追記:
FILE *fp = fopen("log.txt", "a");
if (fp != NULL) {
fprintf(fp, "ログメッセージ\n");
fclose(fp);
}
バイナリモード:
// バイナリ読み取り
FILE *fp = fopen("image.png", "rb");
// バイナリ書き込み
FILE *fp = fopen("output.bin", "wb");
C言語のポイント:
fopenの戻り値をチェック(NULL = エラー)- 必ず
fcloseでファイルを閉じる - バイナリモードは必ず
bを付ける(Windowsで重要)
Java でのモード指定
Javaではクラスによってモードが決まります。
読み取り:
import java.io.*;
// テキストファイル読み取り
try (BufferedReader reader = new BufferedReader(
new FileReader("data.txt", StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
書き込み:
// テキストファイル書き込み
try (BufferedWriter writer = new BufferedWriter(
new FileWriter("output.txt", StandardCharsets.UTF_8))) {
writer.write("こんにちは\n");
writer.write("世界\n");
} catch (IOException e) {
e.printStackTrace();
}
追記:
// FileWriterの第2引数にtrueを指定
try (BufferedWriter writer = new BufferedWriter(
new FileWriter("log.txt", StandardCharsets.UTF_8, true))) {
writer.write("新しいログ\n");
} catch (IOException e) {
e.printStackTrace();
}
バイナリファイル:
// バイナリ読み取り
try (FileInputStream fis = new FileInputStream("image.jpg")) {
byte[] data = fis.readAllBytes();
// データ処理
} catch (IOException e) {
e.printStackTrace();
}
// バイナリ書き込み
try (FileOutputStream fos = new FileOutputStream("output.bin")) {
byte[] data = {1, 2, 3, 4, 5};
fos.write(data);
} catch (IOException e) {
e.printStackTrace();
}
Javaのポイント:
- クラス名でモードが決まる(FileReader = 読み取り、FileWriter = 書き込み)
- try-with-resources文で自動クローズ
- 追記は
FileWriterの第2引数で指定
JavaScript (Node.js) でのモード指定
Node.jsのfsモジュールを使います。
同期的な読み取り:
const fs = require('fs');
// テキストファイル読み取り
const content = fs.readFileSync('data.txt', 'utf8');
console.log(content);
同期的な書き込み:
// 書き込み(上書き)
fs.writeFileSync('output.txt', 'こんにちは世界\n', 'utf8');
追記:
// 追記
fs.appendFileSync('log.txt', '新しいログエントリー\n', 'utf8');
非同期版(推奨):
// 非同期読み取り
fs.readFile('data.txt', 'utf8', (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data);
});
// 非同期書き込み
fs.writeFile('output.txt', 'こんにちは\n', 'utf8', (err) => {
if (err) {
console.error(err);
return;
}
console.log('書き込み完了');
});
低レベルなモード指定:
// fsオープンでモード指定
fs.open('data.txt', 'r', (err, fd) => {
if (err) throw err;
const buffer = Buffer.alloc(1024);
fs.read(fd, buffer, 0, buffer.length, 0, (err, bytes) => {
if (err) throw err;
console.log(buffer.toString('utf8', 0, bytes));
fs.close(fd, (err) => {
if (err) throw err;
});
});
});
モードフラグ:
'r': 読み取り'w': 書き込み'a': 追記'r+': 読み書き'w+': 読み書き(新規作成)'a+': 読み書き(追記)
Node.jsのポイント:
- 高レベルAPI(readFile、writeFile)が便利
- 非同期版を使うのが一般的
- エンコーディングは
'utf8'が標準
PHP でのモード指示子
PHPのfopenもC言語と似た構文です。
読み取り:
<?php
// テキストファイル読み取り
$fp = fopen("data.txt", "r");
if ($fp) {
while (($line = fgets($fp)) !== false) {
echo $line;
}
fclose($fp);
}
?>
書き込み:
<?php
// 書き込み
$fp = fopen("output.txt", "w");
if ($fp) {
fwrite($fp, "こんにちは\n");
fwrite($fp, "世界\n");
fclose($fp);
}
?>
追記:
<?php
// 追記
$fp = fopen("log.txt", "a");
if ($fp) {
fwrite($fp, "ログメッセージ\n");
fclose($fp);
}
?>
便利な関数:
<?php
// ファイル全体を読む(簡単)
$content = file_get_contents("data.txt");
echo $content;
// ファイル全体を書く(簡単)
file_put_contents("output.txt", "こんにちは世界\n");
// 追記
file_put_contents("log.txt", "ログ\n", FILE_APPEND);
?>
PHPのポイント:
file_get_contentsとfile_put_contentsが便利- 追記は
FILE_APPENDフラグを使う - エラーハンドリングを忘れずに
モード指示子の実践的な使い方

実際のプログラミングでどう使うか見てみましょう。
例1: ログファイルへの記録
アプリケーションの動作をログに残す場合です。
Python の例:
import datetime
def write_log(message):
"""ログファイルにメッセージを記録"""
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] {message}\n"
# 追記モードでログファイルを開く
with open("app.log", "a", encoding="utf-8") as f:
f.write(log_entry)
# 使用例
write_log("アプリケーション起動")
write_log("ユーザーがログインしました")
write_log("データベース接続成功")
ポイント:
- 追記モード
"a"を使用 - 既存のログは保持される
- タイムスタンプを追加して記録
例2: 設定ファイルの読み込みと更新
設定を読んで、一部を変更して保存する例です。
Python の例:
import json
def read_config():
"""設定ファイルを読み込む"""
try:
with open("config.json", "r", encoding="utf-8") as f:
return json.load(f)
except FileNotFoundError:
# ファイルがない場合はデフォルト設定
return {"theme": "light", "language": "ja"}
def write_config(config):
"""設定ファイルに書き込む"""
with open("config.json", "w", encoding="utf-8") as f:
json.dump(config, f, indent=2, ensure_ascii=False)
# 使用例
config = read_config()
print(f"現在のテーマ: {config['theme']}")
# 設定を変更
config['theme'] = 'dark'
write_config(config)
print("設定を保存しました")
ポイント:
- 読み取りは
"r"モード - 書き込みは
"w"モード(全体を更新) - ファイルがない場合の処理も実装
例3: 画像ファイルのコピー
バイナリファイルの扱い方です。
Python の例:
def copy_image(source_path, dest_path):
"""画像ファイルをコピーする"""
try:
# バイナリ読み取りモード
with open(source_path, "rb") as source:
# バイナリ書き込みモード
with open(dest_path, "wb") as dest:
# データをそのままコピー
dest.write(source.read())
print(f"{source_path} を {dest_path} にコピーしました")
except FileNotFoundError:
print(f"エラー: {source_path} が見つかりません")
except Exception as e:
print(f"エラーが発生しました: {e}")
# 使用例
copy_image("photo.jpg", "photo_backup.jpg")
ポイント:
- バイナリモード
"rb"と"wb"を使用 - テキストモードだとデータが壊れる
- 画像、動画、音声などはすべてバイナリモード
例4: CSVファイルの追記
データを蓄積していく例です。
Python の例:
import csv
import datetime
def add_record(name, score):
"""スコアデータをCSVに追記"""
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 追記モードでCSVファイルを開く
with open("scores.csv", "a", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow([timestamp, name, score])
# ファイルがない場合はヘッダーを作成
def initialize_csv():
"""CSVファイルを初期化"""
try:
with open("scores.csv", "x", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["日時", "名前", "スコア"])
except FileExistsError:
pass # すでにファイルがある場合は何もしない
# 使用例
initialize_csv()
add_record("山田太郎", 95)
add_record("佐藤花子", 88)
add_record("鈴木一郎", 92)
ポイント:
- 追記モード
"a"でデータを蓄積 - 初回は
"x"モードで新規作成 - CSVモジュールと組み合わせて使用
例5: 大きなファイルの処理
メモリを節約して大きなファイルを処理する例です。
Python の例:
def process_large_file(input_path, output_path):
"""大きなファイルを1行ずつ処理"""
line_count = 0
with open(input_path, "r", encoding="utf-8") as infile:
with open(output_path, "w", encoding="utf-8") as outfile:
for line in infile:
# 各行を処理(例: 大文字に変換)
processed = line.upper()
outfile.write(processed)
line_count += 1
# 進捗表示
if line_count % 10000 == 0:
print(f"{line_count}行処理完了")
print(f"処理完了: 合計{line_count}行")
# 使用例
process_large_file("large_data.txt", "processed_data.txt")
ポイント:
- ファイル全体を読み込まず、1行ずつ処理
- メモリ使用量を抑えられる
- 巨大なログファイルの処理などに有効
モード指示子でよくあるエラーと対処法
エラー1: FileNotFoundError(ファイルが見つからない)
状況:
読み取りモード"r"でファイルを開こうとしたが、ファイルが存在しない。
エラーメッセージ例:
FileNotFoundError: [Errno 2] No such file or directory: 'data.txt'
対処法:
# 方法1: try-except で処理
try:
with open("data.txt", "r") as f:
content = f.read()
except FileNotFoundError:
print("ファイルが見つかりません。デフォルト値を使用します。")
content = ""
# 方法2: 存在確認してから開く
import os
if os.path.exists("data.txt"):
with open("data.txt", "r") as f:
content = f.read()
else:
print("ファイルが存在しません")
content = ""
エラー2: PermissionError(権限エラー)
状況:
ファイルを開く権限がない、または他のプログラムが使用中。
エラーメッセージ例:
PermissionError: [Errno 13] Permission denied: 'system.log'
対処法:
try:
with open("file.txt", "w") as f:
f.write("データ")
except PermissionError:
print("ファイルへのアクセス権限がありません")
print("管理者権限で実行するか、ファイルが使用中でないか確認してください")
エラー3: UnicodeDecodeError(文字コードエラー)
状況:
テキストモードで開いたが、エンコーディングが合っていない。
エラーメッセージ例:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 0
対処法:
# 方法1: 正しいエンコーディングを指定
with open("data.txt", "r", encoding="shift_jis") as f:
content = f.read()
# 方法2: エラーを無視
with open("data.txt", "r", encoding="utf-8", errors="ignore") as f:
content = f.read()
# 方法3: 自動判定ライブラリを使う
import chardet
with open("data.txt", "rb") as f:
raw_data = f.read()
result = chardet.detect(raw_data)
encoding = result['encoding']
with open("data.txt", "r", encoding=encoding) as f:
content = f.read()
エラー4: データが消えた(’w’モードの誤用)
状況:
既存ファイルを"w"モードで開いて、データが全部消えてしまった。
原因:
# これは危険!既存データが消える
with open("important_data.txt", "w") as f:
f.write("新しいデータ") # 既存の内容は削除される
対処法:
# 追記する場合は "a" モード
with open("important_data.txt", "a") as f:
f.write("新しいデータ\n")
# 読んでから更新する場合は "r+" モード
with open("important_data.txt", "r+") as f:
content = f.read()
# 既存の内容を使った処理
f.write("\n追加データ")
# 一部を書き換える場合
# 1. 読み込む
with open("data.txt", "r") as f:
content = f.read()
# 2. 処理する
modified_content = content.replace("旧", "新")
# 3. 書き込む
with open("data.txt", "w") as f:
f.write(modified_content)
エラー5: ファイルが閉じられていない
状況:
close()を忘れて、ファイルハンドルが残り続ける。
問題のあるコード:
# 良くない例
f = open("data.txt", "w")
f.write("データ")
# close() を忘れた!
対処法:
# 方法1: with文を使う(推奨)
with open("data.txt", "w") as f:
f.write("データ")
# 自動的に閉じられる
# 方法2: try-finally を使う
f = open("data.txt", "w")
try:
f.write("データ")
finally:
f.close() # 必ず実行される
モード指示子使用のベストプラクティス
原則1: with文を使う
ファイルを確実に閉じるため、with文を使いましょう。
良い例:
with open("file.txt", "r") as f:
content = f.read()
# ここでファイルは自動的に閉じられる
悪い例:
f = open("file.txt", "r")
content = f.read()
f.close() # 忘れる可能性がある
原則2: 適切なモードを選ぶ
用途に合ったモードを使いましょう。
チェックリスト:
- 読むだけ? →
"r" - 新しく書く?既存のデータは不要? →
"w" - 追加する?既存のデータは保持? →
"a" - 読み書き両方? →
"r+"、"w+"、"a+" - テキスト? → そのまま
- バイナリ(画像など)? →
"b"を追加
原則3: エンコーディングを明示する
テキストファイルは必ずエンコーディングを指定しましょう。
良い例:
with open("file.txt", "r", encoding="utf-8") as f:
content = f.read()
悪い例:
with open("file.txt", "r") as f: # エンコーディング未指定
content = f.read()
# プラットフォームによって動作が変わる
原則4: エラーハンドリングを忘れずに
ファイル操作は失敗する可能性があります。
良い例:
try:
with open("file.txt", "r") as f:
content = f.read()
except FileNotFoundError:
print("ファイルが見つかりません")
content = ""
except PermissionError:
print("アクセス権限がありません")
content = ""
except Exception as e:
print(f"予期しないエラー: {e}")
content = ""
原則5: バイナリファイルはバイナリモード
画像、動画、音声などは必ずバイナリモードを使いましょう。
良い例:
with open("photo.jpg", "rb") as f:
data = f.read()
悪い例:
with open("photo.jpg", "r") as f: # テキストモード
data = f.read()
# データが壊れる可能性がある
原則6: 大きなファイルは一度に読まない
メモリ効率を考えて、行単位で処理しましょう。
良い例:
with open("large_file.txt", "r") as f:
for line in f:
process(line) # 1行ずつ処理
悪い例:
with open("large_file.txt", "r") as f:
content = f.read() # 全部読み込む
# ファイルが巨大だとメモリ不足になる
まとめ: モード指示子を正しく使おう
モード指示子について解説してきました。最後にポイントをまとめます。
重要ポイント:
- モード指示子はファイルの扱い方を指定する記号
- ‘r’(読み取り)、’w’(書き込み)、’a’(追記)が基本
- バイナリファイルには’b’を追加(’rb’、’wb’など)
- with文を使って確実にファイルを閉じる
- エンコーディングを明示(UTF-8推奨)
- エラーハンドリングを忘れずに
モード指示子は、プログラミングの基本中の基本です。
最初は"r"と"w"の違いを間違えたり、バイナリモードを忘れたりするかもしれません。でも、使っていくうちに自然と身につきますよ。
特に重要なのは、‘w’モードは既存データを削除するという点です。これを忘れると大切なファイルが消えてしまうので、十分注意してくださいね。
それでは、実践的なプログラミングライフを!


コメント