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

phpについて質問です。
csvファイルを読み込み→上書きするスクリプトを作ってみましたがうまく行かないときがあり原因を考えています。
100行程度のcsvから任意の行($idで指定したもの)を書き換えたいのですが、どこかに間違いや改善点があればお願いします。
うまく動作しない理由が知りたいです。

<?php
//データの取り出し
$id = $_GET['id'];
$data = file("../data/file.csv");

//idで指定した行に書き込み
$data[$id] ="テスト書き込み";

//csvファイルにデータの書き込み
$file = fopen("data/file.csv","w+");
flock($file, LOCK_EX);
for($i=0; $i<count($data); $i++) {
fwrite($file,$data[$i]);
}
fclose($file);
?>


●質問者: hanabusatsukasa
●カテゴリ:ウェブ制作
✍キーワード:CSV Flock PHP スクリプト テスト
○ 状態 :終了
└ 回答数 : 7/7件

▽最新の回答へ

1 ● m-nisi
●17ポイント

$data = file("../data/file.csv");

$file = fopen("data/file.csv","w+");

ファイルの場所が違うみたいですけど、

これはいいのでしょうか?

http://q.hatena.ne.jp/answer

◎質問者からの返答

すみませんこれは単純ミスです。

「テスト書き込み」が書き込まれるときとそうでないときがあるんですよね。。。


2 ● b-wind
●18ポイント

ざっと見る限り、

・上書き処理なのに、file 関数と fopen 関数に指定しているファイル名が違う

・マニュアルには file 関数は LOCK を取得するという表記は無い。同時リクエストがあった時にファイルは壊れる可能性が高い。

ところが疑問に思いました。

http://q.hatena.ne.jp/1162570238

◎質問者からの返答

すみません、ファイルのアドレスは単純ミスです。

「テスト書き込み」が書き込まれるときとそうでないときがあるんですよね。。。このスクリプトはhttp://php.s3.to/tt/tt4.phpここを見て作りました。lockは間違っているでしょうか、、、


3 ● iketerummo
●17ポイント

closeの前にunlockが抜けている

flock($file, LOCK_UN);

Lock間の処理時間を短くすればそれなりの要求にも対応させられます。

同時書き込み数件程度であれば問題ないと当方でテスト済み。それ以上であればDBのトランザクションをお使いください。

http://jp2.php.net/manual/ja/function.flock.php

◎質問者からの返答

ありがとうございます。

アンロックつけてみます。

根本的に違ってないようなのでうまく動作するときとしないときの差は、、もしかしたら契約しているサーバがあまりにも安価なところだったためかもしれないですね。


4 ● iketerummo
●17ポイント

http://testwiki.仮.jp/?PHP%2F%A5%D5%A5%A1%A5%A4%A5%EB%A5%ED%A5%C3%A5%AF%2F%A5%CE%A1%BC%A5%C8#f4a10010

補足:

もっと厳密に更に精度を上げたいのであればバッファを考慮することと、戻り値(flock,fclose)を取得し例外を追加してください。

そこまで精度を上げるなら、尚更DBのほうが良いという結論になってしましますが。。。

◎質問者からの返答

バッファ、知りませんでした勉強になります。


5 ● tobeoscontinue
●17ポイント
$id = $_GET['id'];

$idを添字として使っているので数字かどうかチェック(http://q.hatena.ne.jp/1114406105]is_numericしてis_int)した方がいいでしょう。また代入する前に添字の範囲チェックもした方がいいでしょう。


$data[$id] ="テスト書き込み";

問題はこの代入でしょう。行の識別をfile()によって行っているので改行文字が必要です。これでは次の行と結合してしまい、上書きではなく、行の削除と挿入になってしまいます。

$data[$id] ="テスト書き込み\n"; // osによっては\r\nかも

書き込みはforもいいですがforeachの方が綺麗です。

またimplode()で長い文字列にして書き出すのも手です。

また上書きではなく、別の名前で書き出してオリジナルをリネームし、

書き出したファイルをリネームするとした方が安全です。

まぁ数百行のファイルで書き込めないという状況にはならないと思いますが。


ロックについては書き込みの時点では不十分でしょう。するならロックしてからReadしてWriteするようにしないと厳密にはまずいでしょう。

file()はパスしか受けつけないのでfgets()でfile()のような機能を作らないといけなくなるので面倒ですが。

◎質問者からの返答

やはり、

$data[$id] ="テスト書き込み\n";

こちらが動作するときと

指定した$id行が空欄になってしまうときがあります。

スクリプトを改善したので契約サーバに問題があるのでしょうか??


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


●質問をもっと探す●



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