【PHP入門2021】ファイルから1文字ずつ読み込む関数fgetcの使い方

PHP

fgetc関数の基本構文

ファイルから1文字ずつ読み込む

fgetc ( resource $handle) : string|false

パラメータ

名前 初期値 説明
resource $handle fopenで取得したファイルポインタを管理するリソース型のオブジェクト(ファイルハンドラやファイルストリームと同意)

返り値(戻り値)

説明
string|false 次のポインタの1文字。ファイルの終端ならfalseを返す。

fgetc 関数の使い方

ファイルから1文字ずつ読み込み・書き込みする最低限のサンプルソースコード

最低限のファイル入出力処理です。ロック制御やエラー処理は省略しています。

//=======================================================
// ファイルから1文字ずつ読み込んで、別のファイルにコピーしていくサンプル
//=======================================================

$read_file = 'input/line-1.txt'; //読み込みファイル
$write_file = 'output/line-1.txt'; //書き込みファイル

// ファイルのオープン
$fp_r = fopen($read_file, "rb"); //読み込みファイルオープン
$fp_w = fopen($write_file, "wb"); //書き込みファイルオープン

// 読み込みファイルを1文字ずつ読み込みループする
while (($buffer = fgetc($fp_r)) != false) {

	// 書き込みファイルに1文字ずつファイルに書き込み
	if(fwrite($fp_w, $buffer) === false){
		throw new Exception("書き込みに失敗しました");
	}

}

fclose($fp_r); //読み込みファイルクローズ
fclose($fp_w); //読み込みファイルクローズ

ファイルから1文字ずつ読み込み・書き込みするサンプルソースコード【ロック&エラー処理あり完全バージョン】

こちらはロック制御やエラー処理を入れたバージョンです。

とっても長いですがWebの本番サービスで同時アクセスの可能性があるファイル処理をやろうとした場合はこれがむしろ最低限のコードになります。

//=======================================================
// ファイルから1文字ずつ読み込んで、別のファイルにコピーしていくサンプル
//=======================================================

$start = microtime(true); //開始時間記録
$read_file = 'input/line-1.txt'; //読み込みファイル
$write_file = 'output/line-1.txt'; //書き込みファイル

try{

	echo "処理開始 コピー {$read_file} => {$write_file}" . PHP_EOL;

	//---------------------------------------
	// 読み込みファイルのオープン&ロック処理
	//---------------------------------------
	$fp_r = fopen($read_file, "rb");
	if(is_resource($fp_r) === true){
		echo "読み込みファイルオープン成功 {$read_file}" . PHP_EOL;
		if (flock($fp_r, LOCK_SH) === true) { // ファイルをロックする(共有ロック)
			echo "読み込みファイルのロック成功 {$read_file}" . PHP_EOL;
		}else{
			throw new Exception("読み込みファイルのロック失敗 {$read_file}");
		}
	}else{
		throw new Exception("読み込みファイルオープン失敗 {$read_file}");
	}

	//---------------------------------------
	// 書き込みファイルのオープン&ロック処理
	//---------------------------------------
	$fp_w = fopen($write_file, "wb");
	if(is_resource($fp_w) === true) {
		echo "書き込みファイルオープン成功 {$write_file}" . PHP_EOL;
		if (flock($fp_w, LOCK_EX) === true) { // ファイルをロックする(排他ロック)
			echo "書き込みファイルのロック成功 {$write_file}" . PHP_EOL;
		}else{
			throw new Exception("書き込みファイルのロック失敗 {$write_file}");
		}
	}else{
		throw new Exception("書き込みファイルオープン失敗 {$write_file}");
	}

	//---------------------------------------
	// 読み込みファイルを1文字ずつ読み込みループする
	//---------------------------------------
	echo "書き込みファイルの行数: " . count(file($write_file)) . PHP_EOL;
	$line_num = 0;
	while (($buffer = fgetc($fp_r)) != false) {
		++$line_num;

		if($line_num%10000 === 0){ //1000行ごとに進捗出力
			$now = microtime(true); //終了時間記録
			echo "{$line_num}行目 " . number_format($now - $start, 4) . "秒" . PHP_EOL;
		}

		//---------------------------------------
		// 書き込みファイルに1文字ずつファイルに書き込み
		//---------------------------------------
		if(fwrite($fp_w, $buffer) === false){
			throw new Exception("書き込みに失敗しました");
		}
	}

	//---------------------------------------
	//終了後のチェック
	//---------------------------------------
	if (feof($fp_r) === false) {
		throw new Exception("読み込みファイルが最後まで処理されていません {$read_file}");
	}

	echo "書き込みファイルの行数: " . count(file($write_file)) . PHP_EOL;
	echo "正常終了" . PHP_EOL;

}catch(Exception $ex) {

	//---------------------------------------
	// エラー処理
	//---------------------------------------
	echo "エラーメッセージ: " . $ex->getMessage() . PHP_EOL;

} finally { //finallyはPHP5.5より

	//---------------------------------------
	// 後処理。正常終了・エラー終了のいずれにしても実行
	//---------------------------------------
	if (is_resource($fp_r) === true) {
		echo "読み込みファイルロック解除 {$read_file}" . PHP_EOL;
		flock($fp_r, LOCK_UN); //ロック解除
		echo "読み込みファイルクローズ {$read_file}" . PHP_EOL;
		fclose($fp_r);
	}

	if (is_resource($fp_w) === true) {
		echo "書き込みファイルロック解除 {$write_file}" . PHP_EOL;
		flock($fp_w, LOCK_UN); //ロック解除
		echo "書き込みファイルクローズ {$write_file}" . PHP_EOL;
		fclose($fp_w);
	}

}

$end = microtime(true); //終了時間記録
echo "実行にかかった時間: " . number_format($end - $start, 4) . "秒" . PHP_EOL;


exit;

関連するファイルシステム関数

ファイル入出力関数の特徴まとめ

関数 利用シーン 機能 処理単位 ハンドル
の管理
ロック 速度 メモリ節約 安全性 エラー時
fgetc 1文字ずつ処理する 読み 1文字ずつ 別途 別途 × △自前 終端でfalse
fgets 1行ずつ処理する 読み 1行ずつ 別途 別途 △自前 終端かエラー
でfalse
fread 固定バイトごとに
処理する
読み 指定バイト 別途 別途 ○一括
×分割
×一括
○分割
△自前 エラーでfalse
fgetcsv CSVファイルを
1行ずつ読み込む
読み 1行ずつ 別途 別途 × △自前 エラーで0かnull
file ロック不要のファイル
を行ごとに高速処理
&同時アクセスが少ない
読み データ全部 不要 ロックなし × × エラーでfalseや
E_WARNING
file_get_contents ロック不要のファイル
の文字列全体を高速取得
&同時アクセスが少ない
読み データ全部 不要 ロックなし × × エラーでfalseや
E_WARNING
fwrite
fputs
ハンドル利用時の
書込処理全般
書き 指定バイト 別途 別途 ○一括
×分割
×一括
○分割
△自前 エラーでfalse
fputcsv CSVを1行ずつ書込時 書き 1行ずつ 別途 別途 × △自前 エラーでfalse
file_put_contents 1~数回だけ書込する時。
繰り返しは非常に遅い。
書き データ全部 不要 ロック指定可能 ○一括
×分割
×一括
○分割
△フラグ指定 エラーでfalse

ファイルシステム関数一覧

fopen

fclose

flock

feof

fgetc

fgets

fread

fwrite/fputs

fgetcsv

fputcsv

file

file_get_contents

file_put_contents

コメント

タイトルとURLをコピーしました