• ベストアンサー

ファイルの先頭に追加書込みする方法について教えて下さい

今まで、単にファイルの最後にデータを追加するように 下記のように書いていた部分を open(OUT,">>$logfile2") || &error; print OUT "カウント : \[ $pcount \]\n日  時 : \[ $time \]\n"; close(OUT); ファイルの先頭に追加していくようにしたいのですが、うまくいきません。 ミスティーネット・Perl・CGI講座というサイトを参考に下記のようにしてみました。 open(DATA,"+<$logfile2") || &error; seek(DATA,0,0); print DATA "\nカウント : \[ $pcount \]\n日  時 : \[ $time \]\n"; close(DATA); このように書くと追加書込みではなく、書き換えになってしまいます。 また、+<の部分を>>にすると変更前と同様、ファイルの最後に追加されてしまいます。 どこがどういけないのか判る方がみえましたら教えて下さい。 よろしくお願いいたします。

  • CGI
  • 回答数2
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

CGIのカウンターのログファイル程度であれば ############################## $tmp = "\nカウント : \[ $pcount \]\n日  時 : \[ $time \]\n"; open(DATA,"+<$logfile2"); @array = <DATA>; unshift @array, $tmp; seek(DATA,0,0); print DATA @array; close DATA ; ############################### ということも"あり"です。 ただし,ファイルサイズが大きくなると,それなりに処理に時間がかかってしまいますので,お気をつけて。

kyonmimi2006
質問者

お礼

maniacpapaさん、アドバイスありがとうございます。 サイズが大きくなると、処理時間がかかるという点、全てのデータを残す必要はないため、spliceで対処できそうな気がします。 どうもありがとうございました。

その他の回答 (1)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

残念ながらすでにあるファイルの先頭にデータを追加するとか、途中にデータを割り込ませる ということはできません。 ですので、 ・新しくファイルをオープンして ・追記したいデータを書き込み ・古いファイルの内容をその後ろにコピーする ・古いファイルを削除 ・新しいファイルを古いファイルの名前でセーブする というような手順をとる必要があります。 もし古いファイルの大きさがそれほどでもないのなら、 ・読み書き可能モードでファイルをオープン ・ファイルの内容を全部読み出して変数に格納しておき ・ファイルポインタを先頭に戻して ・追加したいデータを書き出して ・最初に読み取ったデータをその後に書き戻す というやり方でもよいでしょう。 モジュールを使ってよいのなら、Tie::Fileが使えます。 http://www.kt.rim.or.jp/~kbk/perl-5.8/perlfaq5.html#how_do_i_change_one_line_in_a_file_delete_a_line_in_a_file_insert_a_line_in_the_middle_of_a_file_append_to_the_beginning_of_a_file Tie::File - Access the lines of a disk file via a Perl array - search.cpan.org http://search.cpan.org/~mjd/Tie-File-0.96/lib/Tie/File.pm

kyonmimi2006
質問者

お礼

sakusaker7さん、こんにちは。 簡単にはできなさそうですね。 カウンタのデータを見るのにいちいち、最後尾までスクロールするのが面倒だったので簡単に変更できればと思ったのです。 もっと勉強してモジュールのことがわかってから、つくります。 どうもありがとうございました。

関連するQ&A

  • ログファイルの記録数

    # ログ更新 unshift(@new,"$num<>$addr\n"); open(OUT,">$logfile") || &error("Write Error: $logfile"); print OUT @new; close(OUT); 上記ログの書込みに、最大保存数を設定したいのですが、どのようにすればいいのでしょうか。 $max = 3; とした場合、3行超えたら古いファイルを消したいと考えています。よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • ファイルの書き込み2

    またまた失礼します。 やりたいことは以下です。 1.ディレクトリを開く。 2.ファイル達を読み込み。 3.追記用のデータファイルを開く。 4.「2」にデータを追記 5.別のディレクトリに書き出し。 以上です。 4番がうまくいきません。 ためしに4の工程を抜かすと問題なく書き出されます。 4の工程でやりたいことは、 1.タブ区切りのテキストファイルを読み込み。 2.書き出し用に読み込んだ(追記したいファイル)<productのpath="[ココの値!]"を取得。 3.「2」番で取得した値と「1」番で取得した値を比較。 4.「3」がtrueの行を追記して書き出し。 以上。 要するになにがしたいかというと、 仮にタブ区切りテキストには10行分のデータがあるとします。 それぞれの行には3つ分の値が入っており、先頭にIDが付いています。 一番最初に読み込んだファイル(追記したいファイル)にも同様にIDが振られており(<product path="ココ")そのIDとタブ区切りテキストのIDが一致した行だけ追記したいということです。 下記のコードだとなぜか、 10行分のデータがすべて追記されてしまいます。 コードは以下です。 #!/usr/bin/perl #既存ファイル読み込み&追記 $n_dir = "newXml/"; $b_dir = "xml/"; opendir(DIR, $b_dir); while($file = readdir(DIR)){ $bfile="$b_dir$file"; $nfile="$n_dir$file"; $dfile="data/data.txt"; if (-T $bfile) { open(IN, $bfile);#既存ファイルオープン @list = <IN>; close(IN); open(OUT,">$nfile");#書き出しファイルオープン foreach $line (@list) { if ($line =~ /\<product/){ $line =~ /path=\".*\"/;#path取得 $1; } if ($line =~ /\<\/product\>/) { open(IN, $dfile);#追加データファイルオープン while($data = <IN>){ chomp(@data = split(/\t/,$data)); $data[0] =~ s/\//_/g; if($data[0] == $1){#取得したパスとdata.txtとってきた値を比較 print OUT <<EOF; <ds path="$data[0]">$data[1]</ds> <kw>$data[2]</kw> $line EOF } else{next;} } close(IN) }else{print OUT $line;} } close(OUT); } else{next;} } closedir(DIR); 長々と申し訳ありません。 エラーなどは特にありません。 ご協力お願いします。

    • ベストアンサー
    • Perl
  • 配列の一部を書き換えてファイルに保存する方法は?

    $dicname ='GermJ.txt'; open(IN, "$dicname"); @list = <IN>; close(IN); 読み込んだ配列@listの5番目のデータを'aaaaaaaaaa'に書き換えたいのですが、 $list[5]='aaaaaaaaaaaaaaaaa'; open(OUT, "> $dicname"); foreach (@list) { print OUT $_; } close(OUT); とやって、ファイルの中身を調べると、6番目の文字列データが5番目の文字列データの後ろにくっついてしまっています。 改行マークを $list[5]='aaaaaaaaaaaaaaaaa',\n;のように行末に追加しても、次の行とのあいだに空間が生まれます。基本的なファイル書き込みの知識をお尋ねして申し訳ありませんが,どうかお教えください。

    • ベストアンサー
    • Perl
  • ファイルの作成時刻と更新時刻

    open(OUT,">>$file"); print OUT "$value\n"; close(OUT); で作成したファイルの $time_stamp_9 = localtime((stat("$file"))[9]); $time_stamp_10 = localtime((stat("$file"))[10]); で取得したとき常に同じ値になるのですが、追加書き込みでもその様になるのでしょうか?よろしくお願い致します。 #(stat($file))[9];#最終更新時刻 #(stat($file))[10];#作成時刻

    • ベストアンサー
    • Perl
  • perlでファイルへの書き込みができません!

    perlでファイルへの書き込みができません! 教えてください. webプログラミング初心者なのですが, フォームから送信されたデータをshift-jisに変換させてからbbs1.txtへの内容の書き出しを行いたいのですが, #!/Applications/XAMPP/xamppfiles/bin/perl print "Content-type: text/html; charset=utf-8\n\n"; # フォーム部分を表示する print <<EOL; <html> <body> <h2>一行掲示板</h2> <form method="post" action="bbs1.cgi"> メッセージ:<input type="text" name="message" size="60"> <input type="submit" value="送信"> </form> <hr> EOL &ReadParse(*form); # フォームの値を取得 $message = $form{"message"}; use Encode; use Encode::Guess qw(euc-jp shiftjis 7bit-jis); encode("shiftjis",decode('Guess',$message)); # ログファイル読み込み open(IN, "bbs1.txt"); @log = <IN>; close(IN); # メッセージが入力されているときは書き込み処理を行なう if ($message ne "") { # ログ先頭にメッセージを格納 unshift @log, "$message\n"; # ログファイルに書き込み open(OUT, "> bbs1.txt"); print OUT @log; close(OUT); } # ログ表示 foreach $data (@log) { chop $data; print "$data<br>\n"; } print "</body>\n</html>\n"; このような感じにし実行して後でtxtファイルを見ると何も書かれていません>< なぜでしょうか...? 教えて下さい>< 今気づいたのですがそれに関連してなのかログも表示されていませんでした...>< txtファイルのアクセス権は読み書き可になっています encodeはあえてつかっています.

    • ベストアンサー
    • Perl
  • 指定行に書込み

    open( IN, "log.cgi" ); @f_data = <IN>; close( IN ); $i = '1'; open( OUT, ">dat.cgi" ); select OUT; print "document.open();\n"; print "document.write('"; foreach( @f_data ){ if( $i > 5 ){ last; } ( $f_data1, $f_data2, $f_data3, $f_data4 ) = split( /<>/ ); $f_data1 =~ s/ //g; print "$f_data1"; $i++; } print "');\n"; print "document.close();\n"; select STDOUT; close( OUT ); 上記スクリプトで、指定された行数、又は指定された場所でdat.cgiに 書き出したいのですが、どのように書けばよろしいのでしょうか? 例えば、 ・100行目に書き出す。 または、 ・指定された文字列の間に書き出す。 (例)<!--開始-->ここに書き出す。<!--終了--> このどちらかが出来ればいいのですが、上記スクリプトをどのように変更すれば可能になるでしょうか?お手数ですが、どうぞ宜しくお願いいたします。

    • ベストアンサー
    • Perl
  • ログファイルの新規作成方法について

    初心者の質問ですが、分かる方がいらっしゃればお願いします。 予め設置されたファイル(abcd.txt)を開いて書き込み保存は下記の構文でわかります。 もし、ファイルがない状態で新しくabcd.txtの作成と書き込みをするにはどうすればよいのでしょうか? open(OUT,">>abcd.txt"); print OUT "$sampleA,$sampleB,$sampleB\n"; close(OUT);

    • ベストアンサー
    • CGI
  • splice()の使い方について教えて下さい

    ホームページのカウンターで、アクセス解析をしたくてフリーのcgiカウンターに手を加えました。 そして、新しいログが、ファイルの先頭に来るよう下記のようにしました。 $tmp ="\nカウント : \[ $pcount \]\n日  時 : \[ $time \]\nホ ス ト : \[ $host \]\n\n"; open(DATA,"+<$logfile2") || &error; @array = <DATA>; @arr = splice(@array, 2030); unshift @array, $tmp; seek(DATA,0,0); print DATA @array; close(DATA); 以前、こちらのサイトで『新しいデータをファイルの先頭から表示させる方法』について質問させていただきました。 そして、unshift と seek を使った方法を教えていただきました。 ただ、データが多くなるとこの方法では、データが多くなると処理に時間がかかると教えて頂いた為、私は、ログが約90件を超えたら古いデータを消そうと思い、このようにしました。 しかし、『@arr = splice(@array, 2030);』この部分が良くないようで、データの一部が残ってしまうのです。 splice()の使い方について詳しく教えて下さい。 よろしくお願い致します。

    • ベストアンサー
    • CGI
  • データの入れ替え処理が巧くできないのですが

    いつもお世話になります 簡単なDBを作っているのですが、データの更新処理が巧くいかなくててこずっています POSTメッソドで送られてきた name=actionの内容がedit2、の時 sub menteが実行されます同じく name=noの変数には更新したいファイルの番号がセットされます それらを取得して、ファイルを開き $nooの内容(DBのファイル番号)とnoが一致したらブラウザから送られてきたデータと その部分のデータ($nooはデータの先頭で以降<>で区切って変数が格納される) を入れ替える処理を行いたいのですがどの様に書いたらいいのでしょうか、下記のコードですと変数 $_に更新される前のデータしか代入できず結果ファイルの入れ替えは行えません open(IN,"$logfile") || &error("Open Error : $logfile"); while (<IN>) { ($noo,@arg_[0..$#eqipument],@p[0..5],$n_article,$w_article,@reselect_marks) = split /<>/; if ($no == $noo ) { $_ = join('<>',$noo,(map{$arg_[$_]}(0..$#eqipument)),$p0,$p1,$p2,$p3,$p4,$p5,$n_article,$w_article,@reselect_marks,),'<>',"\n"; } push(@new,$_); } close(IN); # 更新 open(OUT,">$logfile") || &error("Write Error : $logfile"); print OUT @new; close(OUT); 尚ブラウザから送信されてくるデータは以下のような感じです print qq|<form action=\"$myself\" method=\"POST\">\n|; print qq|<input type=hidden name=mode value=\"admin\">\n|; print qq|<input type=hidden name=action value=\"edit2\">\n|; print qq|<input type=hidden name=no value=\"$no\">\n|; 宜しく御教授お願いいたします。

    • ベストアンサー
    • Perl
  • CSVデータの編集の際の重複チェックの方法

    今、data.csv(カンマ区切り)として、左から順位、名前、性別という3項目で、10人程度のリストデータがあります。 data.csv(カンマ区切り)を編集するようにしていますが、順位は重複してはならないので、重複していたらエラーを出したいのですが。。。 ($rank,$name,$sex) = split(/\,/,$line); です。 open(IN,"$logfile") || &error("ファイルが開けません"); @lines = <IN>; close(IN); # 情報の書換え foreach $line (@lines) { ($rank,$name,$sex) = split(/\,/,$line); $line = "$in{'rank'},$name,$sex\n";} push(@new,$line); } # ファイルを更新 open(OUT,">$logfile") || &error("ファイルが開けません"); print OUT @new; close(OUT);

専門家に質問してみよう