• ベストアンサー

ファイルの上書き

初心者です。 ファイル(count.dat)にデータのカウント数を上書きしていきたいのですが、実行しますとファイルが壊れてしまいどこで失敗しているのか分かりません。。 以下のように記述したのですが、アドバイス頂けないでしょうか。 ちなみにcount.datの中身は以下の通りです。 0,0 1,0 2,0 3,0 4,0 5,0 6,0 $max_numの値が別に算出されており、$max_numが1だったら上記の1,0を1,1に、$max_numが2だったら上記の2,0を2,1に上書きしたいと思っています。$max_numでない部分(3,0や4,0や5,0)はそのまま変更なしで保存させたいです。 #ファイルの読み込み $num=0;#過去の人数 $qNo=0;#Qナンバー $l=0; open openDat,'<count.dat' or die "file not Exist!!"; while (<openDat>){ $a[l]=$_; $qNo=substr($a,0,1); if($max_num=$qNo){       $num[l]=substr($a[l],2); $num[l]+=1; $a[l]="$qNo".","."$num[l]"; print $a[l]; }else{ $num[l]=substr($a[l],2); } $l+=1; } close openDat; open openDat,'>count.dat' or die "file not Exist!!"; for( $j=0; $j<=6; $j++) { print openDat $l,"\n"; } close openDat;

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

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

  • ベストアンサー
  • g_p_
  • ベストアンサー率53% (28/52)
回答No.3

こんにちは、 >ファイルが壊れてしまいどこで失敗しているのか分かりません。。 >for( $j=0; $j<=6; $j++) { >print openDat $l,"\n"; >} これは、6回ループして、$lと改行 を出力しています。 #2氏の >perl の文法や表現の基礎について もう少し学んだほうが良いでしょう。 これは真摯に受け止めていただくとして、 一旦、配列にバッファしてから書き戻すのは ファイルが大きくなると問題がありますが、 質問文スクリプトと比べる為の参考として書いてみます。 #! /usr/bin/perl use strict; use warnings; my $file_name = 'count.dat'; my $max_num = 1; my @lines = (); open my $fh , '+<' , $file_name or die "open error :$!"; flock $fh , 2 or die "lock error :$!"; while ( my $line = <$fh> ) { if ( my( $count ) = $line =~ /^ $max_num \, (\d+) $/xms ){ $line = $max_num . ',' . ++$count . "\n"; } push @lines , $line; } seek $fh , 0 , 0; truncate $fh , 0; print {$fh} @lines; close $fh; __END__ 参考までに。

その他の回答 (2)

  • xiade
  • ベストアンサー率64% (88/137)
回答No.2

答えを差し上げてもためにならないのでヒントを差し上げます: もっとも質問ごと削除されちゃうかもしれませんが。 ◇明らかに変なところ その1 > $a[l]=$_; >      $num[l]=substr($a[l],2); > $num[l]+=1; > $a[l]="$qNo".","."$num[l]"; > print $a[l]; > $num[l]=substr($a[l],2); ・これじゃ みんな [0] 相当ですね ◇明らかに変なところ その2 > for( $j=0; $j<=6; $j++) { > print openDat $l,"\n"; ・$j がまったく絡んでないけど何のためのループ変数? ・そして、その1 を直したとしてもここから出てくるものは明らかに… ◇他と釣り合っていないところ > $qNo=substr($a,0,1); ・なぜここだけスカラ? 以上をもとにもう少し考えてみてください。 perl の文法や表現の基礎について もう少し学んだほうが良いでしょう。 ロジック面では カンマ区切りなのに 固定長文字列切り出しでやろうとしているあたりにもやや無理もあります(1桁のうちは動くでしょう)

  • g_p_
  • ベストアンサー率53% (28/52)
回答No.1

こんにちは、 ざっと見ですけど、 >$a[l]=$_; 配列のインデックスが変数になってませんよ。 use strict;だったら実行前にエラーになると思います。 短いスクリプトでもやっぱり use strict; は必須だと思います。

関連するQ&A

  • perlです。配列ファイルをよみこんで、1つの要素を上書きする方法

    配列のファイルがあり、それをよみこんで、1つの要素だけ上書きして保存する方法を教えてください。 ex. file.datを以下のようなファイルだとして・・・ あいうえを かきくけこ さしすせそ たちつてと file.datが、 さしすせそ となるようにしたいのです。(つまり、三番目の要素を取り出し、上書き保存するというもの) 以下のように書いてみましたがうまく動きません。 open()やclose()は一回使うだけでいいように、読み書き両用で開いてみました。 $_にはファイル名が入っています。 open(FILE,"+<$_"); @temp=<FILE>; $temp2=$temp[2]; print FILE $temp2; close(LOGFILE); +<を+>とすると、ファイルが空(何も無くなる)となります。 まず読み専用で開いて、ファイルを閉じた後。上書き用で開いたほうがいいのでしょうか??

    • ベストアンサー
    • CGI
  • カウンターで重複カウントの防止について

    勉強がてら以下のようなカウンターをつくりたいと思っています。 1 画像つきのカウンタである 2 重複カウンタを防止したい 3 昨日と今日のカウンターも表示させたい で、2でけつまずきました。 何がいけないのでしょうか? 以下のプログラムだと更新毎にカウンターが回ってしまいます。 ご指摘下さい。よろしくお願い申し上げます。 #!C:\Perl\bin\perl $flg = 0; #IPアドレスの取得と重複カウントの防止============ $ipadd = $ENV{'REMOTE_ADDR'}; #IPアドレスの取得 open (FILE, "<logcount.dat") || die "File Open Err!-logcount.dat\n"; #データをすべて配列logdataに読み込む @logdata = <FILE>; close(FILE); #取得したIPアドレスと履歴のIPアドレスを比較====== for($i=0; $i<=$#logdata; $i++){ if($ipadd eq $logdata[$i]){ #新規のIPデータと過去ログのIPデータが等しかったら $flg = 1; #合致するのは1つのアドレスのみ } } #==================================================================== # $flg = 0 だったら、数をカウント #==================================================================== open(FILE,"<count.dat") || die "File Open Error!-count.dat\n"; #カウントデータの読み込み $count = <FILE>; #変数countにデータを収納 close(FILE); if($flg == 1){ $data = $count; }else{ $data = ++$count; #プラス1をカウント # ログの更新================================== open(FILE, "+<count.dat") || die "File Open Error!\n"; flock(FILE,2); seek(FILE, 0, 0); #.datに上書き保存する為にデータの記位置を調整 print FILE $data; #カウントを記録 flock(FILE,8); close(FILE); # IPアドレスを更新============================= open (FILE, ">>logcount.dat") || die "File Open Err!-logcount.dat\n"; print FILE $ipadd,"\n"; close(FILE); } print $data; #==================================================================== # カウンタの数字に画像を付ける #==================================================================== @count = split(//, $data); foreach $cou(@count){ push(@view, "./img/$cou.gif"); } require "./gifcat.pl"; print "Content-type:image/gif\n\n"; binmode(STDOUT); print &gifcat::gifcat(@view);

    • ベストアンサー
    • Perl
  • flockについて

    ファイルを読み書きする場合に使用するflockですが、closeする前に別ファイルのflockは使用できるのでしょうか? テストしてみたところ、うまくいってるような気もするのですが、確証が持てないので質問させていただきました。 例) $file1="file1.txt"; $file2="file2.txt"; open(OUT,"+<$file") flock(OUT,2); $count1=<OUT>; open(DAT,"<$file2") flock(DAT,1); $count2=<DAT>; close DAT; $count=$count1+$count2; truncate(OUT,0); seek(OUT,0,0); print OUT "$count "; close OUT; ちょっとあえて複雑な書き方としてみましたが、上記のようにflockを使ってる最中に別ファイルのflockを使用することは出来ますでしょうか? 参考URLでも結構ですので、どなたかよろしくお願いいたします。

    • ベストアンサー
    • Perl
  • PHP、外部ファイルにテキストを書きだす。

    こんにちは、皆様。 下記のソースを実行したいと思います。期待する結果としては、外部ファイルに行列に書き出すことです。 <?php $count_file="count.dat"; if(file_exists($count_file)){ $file = fopen("count.dat", "a") or die("file can not open"); $order_no = fgets($file) + time(); print $order_no; }else{ $file = fopen($count_file, "w") or die("file can not open"); $order_no = time(); } set_file_buffer($file,0); flock($file, LOCK_EX); fputs($file , $order_no); flock($file, LOCK_UN); fclose($file); ?> このソースの結果は配列として書き込まれてました。こんな感じです。 129835261512983526501298355377129835537912983566121298356635 このソースを実行する度にcount.datファイルに順次書き出したと思います。 1298352615 1298352650 1298355377 1298355379 1298356612 1298356635 まだまだPHP勉強中なのでわかる方教えてください。 (1)この行で$order_no = fgets($file) + time(); 改行記号をどう付ければ良いでしょうか? (2) C言語のようにポインターで指定しなければならないですか?書き方を教えてください。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • ファイルに書き込めない/ファイルの内容が消える

    編集機能を掲示板につけているところです。 テキストファイルの内容がまったく消えてしまうのです。 どうしてでしょうか? データ形式 314:2006年2月20日(月)22時31分:あああ:いいい:ううう 313:2006年2月20日(月)22時31分:あああ:いいい:ううう 312:2006年2月18日(土)23時18分:あああ:いいい:ううう #コード↓######################################## open(KEIJI, ">keijiban.dat") || die "File 'keijiban.dat' Open Error."; @all = <KEIJI>; $num = $all[0] + 1 if( $num eq '' ); $title = &henkan($form{'title'}); $topic = $form{'topic'}; $message = $form{'message'}; #***** 文字列の置換 ***** $message =~ s/\r\n/<BR>/g; # 日本語表記の日時を得るサブルーチン $time = &jp_time if( $time eq '' ); # 重複があったら置き換えるルーチン foreach(@all){ $data = $_; chop $data; ( $fnum ) = ( split(/:/,$data) )[0]; if ( $fnum == $num ) { $data = "$num:$time:$title:$topic:$message\r\n"; &jcode'convert(*data, 'sjis'); } push @all, $data; } die "File 'keijiban.dat' Open Error."; flock(KEIJI, 2); foreach (@all){ print KEIJI $_,"\n"; } flock(KEIJI, 8); close(KEIJI); ~~~~~~~~~~~~~~~~~~~~~~~~ どんどん手をつけていったら書きこめなくなってしまいました。最初は書き込めていたんですけど・・・。 真ん中あたりのじ「重複があったらおきかえるルーチン」を付け加えていたら書き込めなくなりました。書き込めたときはpushではなくunshiftを使っていました。

    • ベストアンサー
    • Perl
  • 配列の値の操作について教えてください

    num.datの内容が 100 200 300 400 500 の時、以下を実行すると open(IN, "./num.dat"); @number = <IN>; close (IN); $number[0] = $number[0] - 10; open(OUT, ">./num.dat"); print OUT @number; close(OUT); 書き出されたnum.datの内容は 90200 300 400 500 のようになってしまいます。これを 90 200 300 400 500 にしたいのですがどうすればよろしいのでしょうか?くだらない質問ですが、何卒ご教授の程よろしくお願い致します。

    • ベストアンサー
    • Perl
  • substrについて

    入力ファイルから28文字分のファイル名を取り出し、リモートからローカルにダウンロードしたいのですが、substrがうまく働きません。 どのようにすればよいのでしょうか? 以下のとおり記述しています。 open (INPUT,"<$path/$filename") || die "could not open file : $!\n"; print "$path/$filenameファイルをオープンしました。"; print "\n"; while(<INPUT>) { $FTPremotefilename = substr($_,0,28); print "FTPremotefile名は$_です。"; print "\n"; $FTP -> get($FTPremotefile, $FTPlocalfile) || die "Get失敗 $!\n";# ゲット(ファイルのダウンロード) } close (INPUT) || die "could not close file : $!\n"; $_は内容が表示されるのですが、substrで指定した、$FTPremotefileになにも抽出されませんでした。

    • ベストアンサー
    • Perl
  • データファイル中のデータをランダムに整列させる方法

    横70文字縦100文字のデータを横X文字のデータを縦にY行整列させ、その結果をもとのファイルに上書きするプログラムを作成しようとしています。横X文字のデータは最初のデータのどこをとってもよく、他の行の一部とかぶってもいいです。X、Yはランダムです。横にX文字ファイルに上書きしたら、またランダムなX文字を次の行に上書きします。かなり考えましたが、作成したプログラムがうまくいきません。どなたか教えてください。よろしくお願いします。 #! /usr/bin/perl my $filename = "reference.fasta"; open FILE, "+< $filename" or die "$!"; my $tmp; my $count = 0; while(my $c = getc FILE){ next if($c eq "\n"); $array[$count] = $c; $count++; } for($j=0;$j<50;$j++){ $var = int(rand 50); for($i=0;$i<$var;$i++){ # print FILE $array[$j][$i]; $tmp .= $array[$j][$i]; } print FILE $tmp, "\n"; } close FILE;

    • ベストアンサー
    • Perl
  • 昨日と今日のカウンタについて ご指摘下さい

    昨日と今日のカウンタについて カウンターが1こずつではなく、4つとか5つとかずつ増えてしまいます。ですが、html内の <p>本日の数は<img src="./count.cgi?today">です</p> <p>昨日の数は<img src="./count.cgi?yeaday">です</p> を削除すると、ちゃんと1つずつカウントしていきます。(count.datの本日のカウント数もちゃんと1こずつ増えるのを確認しました。) プログラムの何処が間違っているのでしょうか?アドバイスをお願い申し上げます。 <<count.cgi>> #!C:\Perl\bin\perl # 昨日と今日のカウントの取得 $ENV{'TZ'} = "JST-9"; $mday = (localtime(time))[3]; open (FILE, "<logday.dat") || die "File Open Err!-logday.dat\n"; $logday = <FILE>; close(FILE); ($day, $yesday) = split(/:/, $logday); #それぞれ、今日の日付、昨日のカウント数に分ける open(FILE,"<count.dat") || die "File Open Error!-count.dat\n"; $count = <FILE>; #変数countにデータを収納 close(FILE); ($count, $today) = split(/:/, $count); #それぞれ、トータルカウント数、今日の日付のカウント数に分ける # 数をカウント if($day == $mday){ #同日だったなら、トータルと本日のカウントだけ取る。 &totalcount(); }else{ #違っていたら、本日のカウント数を昨日へ、本日のカウントを0に、日にちを修正 $yesday = $today; $today = 0; open (FILE, ">count.dat") || die "File Open Err!-logday.dat\n"; flock(FILE,2); print FILE "$count\:$today"; flock(FILE,8); close(FILE); open (FILE, ">logday.dat") || die "File Open Err!-logday.dat\n"; flock(FILE,2); print FILE "$mday\:$yesday"; flock(FILE,8); close(FILE); &totalcount(); #その後カウントをとる } # 引数受取 $mode = $ENV{'QUERY_STRING'}; $mode =~ s/\W//g; require "./gifcat.pl"; #画像表示のif文================ if($mode eq "total"){ &total(); }elsif($mode eq "today"){ &today(); }else{ &yestaday();} exit; # ログの更新================================ sub totalcount{ open(FILE, "+<count.dat") || die "File Open Error!\n"; flock(FILE,2); $count++; #トータルカウント数にプラス1 $today++; #同じく本日のカウント数にもプラス1 seek(FILE, 0, 0); print FILE "$count\:$today"; flock(FILE,8); close(FILE); } # カウンタの数字に画像を付ける sub total{ #トータルカウンタ============= @countdata = split(//, $count); foreach $cou(@countdata){ push(@view, "./img-t/$cou.gif"); } #画像の出力=============== print "Content-type:image/gif\n\n"; binmode(STDOUT); print &gifcat::gifcat(@view); } sub today{ #今日のカウンタ============= @countdatadt = split(//, $today); foreach $coudt(@countdatadt){ push(@viewdt, "./img-d/$coudt.gif"); } #画像の出力=============== print "Content-type:image/gif\n\n"; binmode(STDOUT); print &gifcat::gifcat(@viewdt); } sub yestaday{ #今日のカウンタ============= @countdatady = split(//, $yesday); foreach $coudy(@countdatady){ push(@viewdy, "./img-d/$coudy.gif"); } #画像の出力=============== print "Content-type:image/gif\n\n"; binmode(STDOUT); print &gifcat::gifcat(@viewdy); } <<count.html>> <html> <head> <title>カウンタ</title> </head> <body> <p>トータルカウント数は<img src="./count.cgi?total">です</p> <p>本日の数は<img src="./count.cgi?today">です</p> <p>昨日の数は<img src="./count.cgi?yeaday">です</p> </body> </html> <<count.dat>> トータル数:本日のカウント数 <<logday.dat>> 今日の日:昨日のカウント数

    • ベストアンサー
    • Perl
  • CGIにおけるサーバへのファイル書込みについて

    [Mon Oct 16 16:27:12 2006] [error] [client 207.46.98.48] Premature end of script headers: prev.cgi [Mon Oct 16 16:27:13 2006] [error] [client 66.249.72.6] damy.dat Cannot Open at /home/e-fresh/public_html/prev.cgi line 71. サーバに上記のようなエラーログがありまして, ファイル作成&書込みができません。 私自身としては,サーバのフォルダに書込み権限が無い事が考えられます が,それをチェックする方法があれば併せてご教示願います。 prev.cgiの中身は下記の通りです。 $damy = 'damy.dat'; open DB,"$d_file" or die "$d_file オープン失敗"; open DAMY,">$damy" or die "$damy Cannot Open"; while (<DB>){            …} close DAMY; close DB; #ダミーファイルをデータファイルにリネーム rename($damy, $d_file) or die "Could not RENAME $damy TO $d_file";

専門家に質問してみよう