@blog.justoneplanet.info

日々勉強

PHP Accessing Files(ファイルへのアクセス)

ファイルから読み込みを行うと、読み込みが完了した位置にファイルポインタが移動する。

■一般的なファイル操作

ファイルを操作するには以下のようにする。まず、fopen関数でファイルをオープンし、flockでファイルをロックする。ファイルハンドラを使う場合、ファイルの全てのデータをメモリに読み込むわけではないので。メモリの節約に繋がる。

<?php
$mask = umask(077);
$fh = fopen('count.txt', 'a+');//0600
umask($mask);
if($fh === false){
    die('Failed to open the file.');
}
if(flock($fh, LOCK_EX)){
    if(filesize('count.txt') === 0){
        $counter = 0;
    }
    else{
        $counter = (int) fgets($fh);
    }
    ftruncate($fh, 0);
    $counter ++;
    fwrite($fh, $counter);
}
fclose($fh);
print($counter);
?>

但し、fgets関数については注意しなくてはならない。

<?php
print(fgets($fh, 1));
//nothing!!
?>

上述のコードを書いてもファイルから文字が読み出されることはない。なぜならば$length-1バイトしか読み込まないためである。従って、以下のように文字数+1の値を記述する必要がある。

<?php
print(fgets($fh, 2));
//1 character is displayed
?>

つうかコノ仕様が非常に覚えづらい。他の関数と統一して欲しい。

各関数について

resource fopen(string $filename, string $mode[, bool $use_inc_path=false[, resource $stream_context]])
第一引数で指定したファイルを、第二引数で指定したモードで開く。ファイルがオープンできなかった場合は、falseを返す。
bool flock(resource $fh, int $mode)
第一引数で指定したファイルハンドラのファイルを、第二引数で指定したモードでロックする。
int filesize(string $filename)
引数で指定したファイルのサイズを取得する。この関数の結果はキャッシュされるので、1リクエスト内に何回もコールし、そのたびに正確な値が必要なときは、clearstatcahche関数をコールする。単位はバイト。
string fgets(resource $fh[, int $length])
ファイルポインタから1行データを取得する。$lengthが設定されていた場合は、$length-1バイト読み出す。
string fgetc(resource $fh)
ファイルポインタから1文字データを取得する。
bool ftruncate(resource $fh, int $size)
第一引数で指定したファイルハンドラのファイルを、第二引数で指定した値の長さにする。元のファイルの余分な部分はカットされ、足りない場合はヌルバイトで補う。
int fwrite(resource $fh, string $data)
第一引数で指定したファイルポインタのファイルに、第二引数で指定した文字列を書き込む。戻り値は書き込んだバイト数(失敗した場合はfalse)。
bool fclose(resource $fh)
オープンしたファイルハンドラをクローズする。ファイルロックをしていた場合は解除する。
int umask(int $mask)
現在のumaskを設定し古いumaskを返す。ファイルを作成する前に適切な権限でファイルが作成されるように調整するために使う。

ファイルオープンのモード

r 読み取り専用(ファイルポインタは先頭)
r+ 読み取り、書き込み専用(ファイルポインタは先頭)
w 書き込み専用(ファイルポインタは先頭、ファイルサイズを0に)
ファイルが存在しない場合は作成を試みる
w+ 書き込み、読み取り専用(ファイルポインタは先頭、ファイルサイズを0に)
ファイルが存在しない場合は作成を試みる
a 書き込み専用(ファイルポインタは最後)
ファイルが存在しない場合は作成を試みる
a+ 書き込み、読み取り専用(ファイルポインタは最後)
ファイルが存在しない場合は作成を試みる
x 書き込み専用でファイルを作る
ファイルが存在する場合はエラーとなる
x+ 読み込み専用でファイルを作る
ファイルが存在する場合はエラーとなる

ファイルのロックモード

LOCK_SH 共有ロック
LOCK_EX 排他ロック

書き込みを行う場合は、排他ロックを使用する。

また、以下のような方法でファイルの文字を全て読み込むことができる。

<?php
if(file_exists('count.txt')){
    $fh = fopen('count.txt', 'r');
    $txt = '';
    while(!feof($fh)){
        $txt .= fread($fh, 1);
    }
    print($txt);
}
?>

各関数について

bool file_exists(string $filename)
引数で指定したファイルもしくはディレクトリが存在するか調べる。但し、ファイルが存在しても、PHPの実行ユーザからアクセスできない場合はfalseを返す。
bool feof(resource $fh)
ファイルポインタがファイル末端に達しているか調べる。
string fread(resource $fh, int $length)
第一引数で指定したファイルハンドラのファイルから、第二引数で指定した$lengthバイト数分だけ読み込む。

■ファイルポインタの移動

<?php
$fh = fopen('count.txt', 'r+');
fseek($fh, 2, SEEK_SET);
?>

各関数について

int fseek(resource $fh, int $offset[, int $whence])
第一引数で指定したファイルハンドラのファイルポインタを、第二引数で指定したバイト数目にセットする。但し、第三引数でSEEK_SETでなく、SEEK_CURを指定した場合は現在の位置からのカウントになり、SEEK_ENDの場合はファイルの末端からカウントする。従って、SEEK_ENDの場合、第二引数は0もしくは負の値となる。
int ftell(resource $fh)
現在のファイルポインタの場所を返す。

■csvファイルの操作

以下のCSVファイルを例に解説する。ちなみに最終行にも改行が必要である。

"Jack","54","USA"
"Emily","18","Japan"

以下のようにfgetcsv関数を用いてcsvファイルの内容を読み出す。また、fputcsv関数を用いて行を追加する。

<?php
$fh = fopen('member.csv', 'r+');
while($row = fgetcsv($fh)){
    print("{$row[0]}({$row[1]})-{$row[2]}" . PHP_EOL);
}
$row = array('John', '28', 'Canada');
fputcsv($fh, $row);
/*
Jack(54)-USA
Emily(18)-Japan
John(28)-Canada
*/
?>

各関数について

array fgetcsv(resource $handle[, int $length[, string $delimiter[, string $enclosure[, string $escape]]]])
第一引数以外はオプションである。デフォルトのデリミターはカンマで、括りはダブルクォーテーションである。
int fputcsv(resource $handle, array $data[, string $delimiter[, string $enclosure]])
第一引数で指定したファイルポインタのファイルに、第三引数以降の引数に基づき、CSV形式の1行分に整形を行った第二引数のデータを書き込む。

■簡易化されたファイル操作

以下のように動画を出力するような場合は、上述の関数を使用するよりもリソースを抑えられる。

<?php
header('Content-type: video/mpeg');
readfile('test.mpg');
?>

また、以下のようにfile_get_contents関数を使用すると、ファイルの内容を全て変数に読み込むことができる。この方法ではメモリに全てのデータを読み込むが、(OSが対応している場合のみ)リソースの消費を抑えるためメモリマッピング技術が使われる。

<?php
$data = file_get_contents('count.txt');
?>
<?php
$data = implode('n', file('count.txt'));
?>

さらに、PHP5では以下のようにfile_put_contents関数を使用し、ファイルに書き込みを行うこともできる。

<?php
$data = 'This is a pen!';
file_put_contents('count.txt', $data, FILE_APPEND | LOCK_EX);
?>

各関数について

int readfile(string $filename[, bool $use_inc_path=false[, resource $stream_context]])
ファイルを読み込んで標準出力に書き出す。
string file_get_contents(string $filename[, bool $use_inc_path=false[, resource $stream_context]])
引数で指定したファイルの内容を文字列として全て読み込む。失敗した場合はfalseを返す。空白のような文字が含まれるURLをオープンする際は、urlencode関数でエンコードする必要がある。
int file_put_contents(string $filename, mixed $data[, int $flags[, resource $context]])
第一引数で指定したファイルに、第二引数で指定したデータを書き込む。第三引数でFILE_APPENDを指定しない場合は、ファイルが上書きされる。また、ファイルを多数のユーザが操作する場合は必ずLOCK_EXを指定する。
array file(string $filename)
ファイル全体を読み込んで配列に格納する。

コメントはまだありません»

No comments yet.

RSS feed for comments on this post.TrackBack URL

Leave a comment