人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

以下のメソッドを使用して、ファイルの書き込みをます。
もしもこの処理時にreturn -1を他に入れた
方がいい場所などはありますか?
知っている方がいましたら教えて下さい。
これで、大体、2000件/日にあるデータを
1ヶ月間list.csvに溜め込みたいです。
同時に書き込む場合などもあると思うのですが
大丈夫でしょうか?
サーバはlinuxっでPHP4以上で処理をします。
function test_wirte($data){
define("CSVFILE_CAMP","/test/list.csv");
$file_csv = CSVFILE_CAMP;
//ファイルオープン
if(!($fno = fopen("$file_csv","a+"))){
return -1;
}
// 排他的ロックを行う
if (flock($fno, LOCK_EX)) {
$bbbb = $data['bbbb'];
$aaaa = $data['aaaa'];
//現在日付の取得
$strDate = date("y-m-d H:i:s");
$str_file = "";
$str_file .= "$strDate";
$str_file .= "\t";
$str_file .= "$bbbb";
$str_file .= "\t";
$str_file .= "$aaaa";
$str_file .= "\t";
$str_file .= "\n";
//ファイル書き込み
fwrite($fno, $str_file);
//ファイルアンロック
// flock($fno,LOCK_UN);
//バッファ関係の不具合対応
fflush($fno);
}else{
return -1;
}
//ファイルクローズ
fclose($fno);
return 0;
}

●質問者: hopefully
●カテゴリ:就職・転職 コンピュータ
✍キーワード:CSV Flock Linux test オープン
○ 状態 :終了
└ 回答数 : 7/7件

▽最新の回答へ

1 ● tadashi0805
●18ポイント

ディスク容量が不足すると、fwrite()もエラーを起こす可能性はあります。

なので、厳密な作りにするなら、fwrite()の戻り値がFALSEかどうかのチェックはいるでしょう。但し、その場合、今の処理でどこまで書き込めたのか、途中まで書き込めたものを元に戻すのかといったRollback処理も必要になるかと思います。

ディスク容量は事実上無制限(不足するようなこはまず起こらない)なら、そこまでの実装は不要かと。

◎質問者からの返答

fwrite()の戻り値がFALSEとかRollback処理とかはどうしたらいいのでしょうか?

サンプルのプログラムなどわかりますか?


2 ● tadashi0805
●17ポイント

fwrite()は、書き込み成功の長さをリターン値で返します。

なので、本当に厳密な処理を行う場合、

・文字列の長さとfwrite()リターン値が合っていればOK

・リターン値の方が短い場合、途中までは書けているので、書けた分を取り除いた文字列をもう一回リトライ

・リターン値がFALSE(この名前でそのまま値として使えます)の場合エラー

です。

http://us2.php.net/manual/ja/function.fwrite.php

また、Rollbackはfseek()関数で行えます。

fwrite()がいきなりFALSEリターンしたら不要ですが、上のリストの2番目(短いリターン)の後FALSEリターンした場合、

fseek($fno, -長さ, SEEK_END)

のようにして、途中まで書いた分を巻き戻してあげます。

http://us2.php.net/fseek

ただ、ここまで行うプログラムは、それほど多くはないと思います。

◎質問者からの返答

そうすると以下の形でいいのでしょうか?

function test_wirte($data){

define("CSVFILE_CAMP","/test/list.csv");

$file_csv = CSVFILE_CAMP;

//ファイルオープン

if(!($fno = fopen("$file_csv","a+"))){

return -1;

}

// 排他的ロックを行う

if (flock($fno, LOCK_EX)) {

$bbbb = $data['bbbb'];

$aaaa = $data['aaaa'];

//現在日付の取得

$strDate = date("y-m-d H:i:s");

$str_file = "";

$str_file .= "$strDate";

$str_file .= "\t";

$str_file .= "$bbbb";

$str_file .= "\t";

$str_file .= "$aaaa";

$str_file .= "\t";

$str_file .= "\n";

//ファイル書き込み

//サーバの容量不足による、書き込めない場合のエラー

if (!fwrite($fno, $str_file)) {

return -1;

}else{

//最大10バイトまで取得

$counter = fgets($fno,10);

$counter++;

fseek($fno, 0);

fputs($fno, $counter); //fwrite($fno, $counter);でもOK

}

//ファイルアンロック

// flock($fno,LOCK_UN);

//バッファ関係の不具合対応

fflush($fno);

}else{

//ロックが出来ない場合のエラー

return -1;

}

//ファイルクローズ

fclose($fno);

return 0;

}


3 ● kurukuru-neko
●17ポイント

1. fopen

NG return -1

2. flock(LOCK_EX)

NG リトライを数回してもNGなら

fclose ;return -1

3. ftell( 現在位置 ) or fstat

(ファイルサイズを得る)

NG flock(LOCK_UN); fclose ; return -1;

4. fwrite

NG 書き込み 0バイト以下:

flock(LOCK_UN); fclose ; return -1

書き込み 1バイト以上:

ftruncate ; flock(LOCK_UN);

fclose; return -1

4. fflush

NG ftruncate ; flock(LOCK_UN);

fclose; return -1

5. flock(LOCK_UN)

NG 無視

6. fclose

NG 無視.

7. return 0

◎質問者からの返答

すいません、よく意味がわからないのですけど?


4 ● kurukuru-neko
●17ポイント

PHPの処理のファイル入出力部分と、リターンの

NGケースの処理のみ処理内容にしました。

補足します。

(一部訂正)

=============

#. NNNNN

NG

==============

# : function test_writeの呼び出すファイル関係

の関数を 抜き出し 順番に1.?8.

NNNN: 呼び出す関数

NG: NGの時に処理すべき内容

1. fopen

NG return -1

2. flock(LOCK_EX)

NG リトライしてもNGなら

fclose ;return -1

※:エラー処理が不十分

3. ftell( 現在位置 ) or fstat

(ファイルサイズを得る)

NG flock(LOCK_UN); fclose ; return -1;

※:現在この処理はない

4. fwrite

NG 書き込み 0バイト以下:

flock(LOCK_UN); fclose ; return -1

※:エラー処理が不足

NG 書き込み 1バイト以上で全部かけていない:

(ファイルサイズを切り詰める)

ftruncate ; flock(LOCK_UN);

fclose; return -1

※:エラー処理が不足

5. fflush

(ファイルサイズを切り詰める)

NG ftruncate ; flock(LOCK_UN);

fclose; return -1

※:エラー処理が不足,

fwriteはバッファリングするので

実際の書き込みはfflush行われエラーになる可能性

がある。

6. flock(LOCK_UN)

NG 無視

7. fclose

NG 無視.

8. return 0

◎質問者からの返答

出来ればソースのサンプルみたいのを

書いて欲しいのですが

可能でしょうか?


5 ● えるふん
●17ポイント

下記のようにすればファイルが壊れずに多重処理ができます.

$tmpname = tmpnam( ...); $fp2 = fopen( $tmpname, "a"); // 常に新規ファイルなので"a"でいい

ようするに一時ファイルで一旦すべての作業をして本番ファイルにすげ替えます.

これでロック(と解除)に失敗,あるいはディスク障害でも起こらなければ多重に処理されてもファイルが壊れることはありません.

tempnam()は一時ファイルを適当な名前で自動で作成しますが,自動で削除はしてくれないので自分で明示的に消してください.

ちなみに

$str_file = "";
$str_file .= "$strDate";
$str_file .= "\t";
$str_file .= "$bbbb";
$str_file .= "\t";
$str_file .= "$aaaa";
$str_file .= "\t";
$str_file .= "\n";

ですが,下記のように記述するともう少し可読性が上がるでしょう。

$body = array();
$body[] = $strDate;
$body[] = $bbbb;
$body[] = $aaaa;
$body[] = "\n";
$str_file = implode( "\t", $body); // http://php.net/implode
◎質問者からの返答

ロックする("transaction.lock"とか適当なファイル名でロックファイルを作る)

がいまいちわかりません。

どうやって作成するのでしょうか?


1-5件表示/7件
4.前の5件|次5件6.
関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ