open関数と +> 記号の使い方とは?

このQ&Aのポイント
  • open関数を +> で用いると、ファイルを開く際に追加書き込みはできないが、読み取り、書き込み、新規作成、上書きは可能です。
  • しかし、実際に使ってみると読み出し機能がうまく動作しないことがあります。
  • この問題の原因と解決方法について紹介します。
回答を見る
  • ベストアンサー

open関数を +> で用いても。。。

モノの本によるとファイルを開く際にファイル入出力記号を +> にすると、追加書き込みは出来ないものの、読み取り、書き込み、新規作成、上書きが出来るとのこと。 ファイルからデータを読み込んで、読み込んだ内容を加工して、すぐにファイルに保存する用途に最適だなと思いましたが、実際に使ってみると読み出しをしてくれません。 何がいけないのでしょうか。 my @s; my @t=('a','b'); open IO,'+>test.txt'; @s=<IO>; print "\$@の要素数は ".@s."個\n"; for(@t) { print IO $_."\n"; } close IO;

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

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

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

「モノの本」とやらの記述で疑問が湧いたら、まずはマニュアルを良くよみましょう。 http://perldoc.jp/func/open > MODE が > の場合、ファイルは出力用に開かれ、既にファイルが ある場合は切り詰められ(上書きされ)、ない場合は新しく作られます。 > ファイルに読み込みアクセスと書き込みアクセスの両方をしたいことを示すために、 > や < の前に + を付けることができます: (略)-- +> モードはまずファイルを上書きします。

makoji
質問者

お礼

ありがとうございます。 おかげさまで +>だけでなく、+<、>>、+>> の違いもよく理解できました。 どちらも貴重なアドバイスになったのですが、ベストアンサーは一つしかつけられないので、文字数で、No.1の方とさせていただきます。 ありがとうございました。

makoji
質問者

補足

ありがとうございます。 これは如何でしょうか。 test.txtを開いてみると、確かに@tの内容で上書きされています。 しかしそれを@sが読み込んでくれません。 <IO>がファイル読み込み時のデータを意味するなら、test.txtは上書きされるのですから、@sに何も入っていないのは当然です。しかしそれなら +> は > とまるで変わらないのではないでしょうか。 my @s; my @t=('a','b'); open IO,'+>test.txt'; for(@t) { print IO $_."\n"; } @s=<IO>; print "\$@の要素数は ".@s."個\n"; close IO;

その他の回答 (1)

  • t-okura
  • ベストアンサー率75% (253/335)
回答No.2

ファイルの読み出し位置を先頭に巻き戻しましょう。 seek IO, 0, 0;

関連するQ&A

  • excel→txtファイル作成時、セル間にできることがある「”」を指すメタ文字

    Perlで書いたプログラムでデータファイルを用いるため、Excel→txt形式(タブ区切り)でファイルを保存し、perlでそのテキストファイルのデータをprintしてみると、セルとセルの間に「”」というような記号が入ってしまうことがあります。 これをsplitで省くことはできますでしょうか?その際に用いるメタ記号も教えていただけないでしょうか?各要素を取り出すためにいい方法があれば教えてください。 (1)元のExcelファイル id 2000 2001 2003 001 A_IN A_IN B_IN 002 B_IN B_IN OUT (2)テキストファイル(タブ区切りで保存) id 2000 2001 2003 001 A_IN A_IN B_IN 002 B_IN B_IN OUT (3)以下のようなperlプログラムでprint表示させると「"」という記号が入ってしまい、要素ごと(例えばA_IN、OUT)にデータ処理を行うことができません。 「プログラム」 #import txt file my $errmsg = "can not open $data\n"; my @data0; open(FID, $data) or die $errmsg; chomp(@data0 = <FID>); close FID; my $number = @data0; for (my $i=1; $i<$number; $i++) { my @a = split(/\r/, $data0$i]); my @b = split(/\t/, $a[0]); print @b, "\n"; ←このprintの結果が以下のようになります。 print $b[0], "\n"; ←そのため、タブによるsplitがうまく print $b[1], "\n";  出来ておらず、これらの値も変 print $b[2], "\n";  なものが出力されてしまいます・・・。 print $b[3], "\n"; } 「結果」 001A_IN"A_IN"B_IN 002B_IN"B_IN"OUT (「”」が入る位置は何回か試したところ、変わることがありました。)

  • perlのopen()で+<を使用した時の挙動が変

    open()で+<を使用すると読み書き両方ができると 理解しましたが、書き込んだ後の結果が 私が思っていた挙動と違っていました。 例えば、 ---test.pl-------------------------- open(FILE,'+<test.txt') or die "$!"; my $line=<FILE>; print FILE "ABC\n"; close(FILE); ---test.txt---- 123 456 789 --------------- を実行すると ---test.txt---- 123 ABC 789 --------------- となることを期待していましたが実際には ---test.txt---- 123 456 789 123 ABC ---------------- となっていました。 1行だけ読み出したときのファイルポインタ は2行目の先頭を指しているように思われますが なぜこのような結果になるのでしょうか。 (Windows7,ActivePerl)

    • ベストアンサー
    • Perl
  • grep関数を用いた複数行からの抽出

    同じ行で重複した単語を削除したいです。 テキストファイル sapporo aomori akita iwate akita yamagata sendai miyagi hukushima miyagi akita mito ・ ・ 上記のようなファイルの同じ行で重複した単語を削除し下の形にしたいです。 sapporo aomori akita iwate yamagata sendai miyagi hukushima akita mito ・ ・ open(FILE1, "<xxx.txt") || die "File1 Open Error! \n"; open(OUT, ">zzz.txt") || die "OUT Open Error! \n"; $string1 = <FILE1>; my @array = split(/\t/,"$string1"); my %count; @array = grep {!$count{$_}++}@array; foreach my $element (@array) { print OUT "$element\t"; } close(FILE1); close(OUT); このプログラムを実行すれば初めの一行は重複した単語を削除できるのですがそこで終了してしまいます。2行目、3行目・・といったように複数行に対して重複した単語を削除するためにはどのようにすればいいのですか。宜しくお願いします。

    • ベストアンサー
    • Perl
  • open関数のファイル操作について

    プログラミング経験ゼロで、CGI及びPerlを勉強しだした者です。 初歩的な質問で恐縮ですが、おわかりになる方ご教授願えますか。 open (ANSWER, ">>data.txt"); print ANSWER "$jikan,$data?n"; close (ANSWER); open関数の箇所を上の様に書いたのですが、自動生成されるはずのdata.txtファイルが見当たりません(CGI-Executablesフォルダ内) ではということで、data.txtファイルを作ってCGI-Executablesフォルダ内に置いてみたのですが、そちらにも書込みされませんでした。 ブラウザではフォーム入力の次に用意した「出力完了」のページに切り替わるのですが、やはり出力はされていないということでしょうか。 どのように修正すれば良いのか困ってます。よろしくお願いします。

    • ベストアンサー
    • Mac
  • 入出力共用が出来ないんです

    カウンターを作ろうとしてるんですけど、入出力共用が出来ないんです。 その部分は open INOUT, "+>$txt";       #$txtはテキストファイルへのアドレス $count = <INOUT>; $count++; print INOUT $count; close INOUT; ってやっています。ここだけコマンドプロンプトで試しているんですが、上手く動きません。"+>$txt"を"+<$txt"としたり、">+$txt"にしたり、最後には、">+<$txt"といろいろ試したんですがダメでした。 ちなみに open IN, "<$txt"; $count = <IN>; close IN; $count++; open OUT, ">$txt"; print OUT $txt; close OUT; ってやると動きます。別にこれでもいいんですが、本には共用出来ると書いてあるのに出来ない、なんかすっきりしません。 入出力共用って出来ないんでしょうか?

    • ベストアンサー
    • CGI
  • ランダムに1行読込み フォーム文字との同異を 判定するには?

    txt ファイル から ランダムに 1行読み込んで それが フォームの入力文字と同じかを 判定し、 同じならば、次のファイルへ飛ぶ には、 どうしたらよいのでしょうか? お教えください。 ------------------------------------------------------ mondai.txt に 問題を 1行に 1題ずつ kotae.txt に 解答を 1行に ひとつずつ 書きました。 mondai.txt の 1行目の 解答が kotae.txt の 1行目 (2行目-10行目、同じ)としました。 001.cgi で 正解すれば 002.cgi を開く 不正解なら もう一度 001.cgi を実行。 問題は ランダムに 表示する。 まず、mondai.txt と kotae.txt を それぞれ 10行にして やってみました。 ------------------------------------------------------ すると、問題は ランダムに表示されました。 しかし、 ##################################################### if (param('answer') eq ("$ans")){ print "Location:$num2.cgi\n\n"; ・・・ { ##################################################### が、うまくいきません。 ↓こうしてあります。どうしたら、よいでしょうか? ↓解答したことを file.txt に記録しよう、ともしています。 ↓ ################ はじめ ############################## #!/usr/bin/perl -T use strict; use warnings; use CGI qw(-debug :standard); my ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year += 1900; $mon = sprintf("%02d", $mon + 1); $day = sprintf("%02d", $day); $hour = sprintf("%02d", $hour); $min = sprintf("%02d", $min); $sec = sprintf("%02d", $sec); my $num = ('1267'); my $num2 = $num + 1; my $value = param('answer'); open(FILE, "../../mondai.txt"); my @data2 = <FILE>; close(FILE); open(FILE, "../../kotae.txt"); my @data3 = <FILE>; close(FILE); my $i = int(rand(10)); my $ans = $data3[$i]; if (param('answer') eq ("$ans")){ print "Location:$num2.cgi\n\n"; open(FILE, '<+file.txt') or die "$!"; my @DATA = <FILE>; close(FILE); open(FILE, '>file.txt') or die "$!"; print FILE ("$num,$ans,$year年$mon月$day日 $hour時$min分$sec秒\n"); print FILE (@DATA); close(FILE); } else { print header(-charset => 'Shift_JIS'); print start_html("$num.cgi"); print ('<font face="century">'); print $data2[$i]; #####---問題表示 print br; print startform( -method => 'POST', -action => "$num.cgi" ); print blockquote( textfield( -name => 'answer', -size => '70', -id => "next", -accesskey => '[' ) ); print <<END; <script type="text/javascript" language="JavaScript"> document.getElementById('next').focus(); </script> END print submit(-value => 'Send ( ↑Alt+[ )'); print endform; } ################ おわり ############################## よろしく、お願いいたします。

    • ベストアンサー
    • Perl
  • ファイルオープンの挙動

    windows環境にてperlの勉強をしております。 http://www.rfs.co.jp/sitebuilder/perl/05/03.html#open を参考にopenを使っておりました。 ファイル書き込みがうまくできていないようなので 以下のようなテストプログラムを作成したのですが 上記のサイトのような挙動をしませんでした。 --source--- #!/usr/local/bin/perl print "Content-type: text/html\n\n"; open(FILE, "+> sample.txt"); $data = <FILE>; print "data = $data<br>"; $flag = print FILE "TEST MESSAGE"; print "flag=$flag<br>"; close(FILE); --source-- --sample.txt-- 実験です --sample.txt-- windows環境だと data = flag= と表示され linux環境(レンタルサーバ)だと data = flag=1 と表示されます。 私の予想では data = 実験です flag = 1 と表示されると思ったのですが何が原因でしょうか。 またlinuxとwindowsで結果が違うのは何か原因があり、 また修正可能でしょうか。 openに+>の挙動例が書いていないサイトもあることが 若干気になります。 もし+>自体が不安定なのでしたら安定して使えるもの をおしえてください。所望の挙動は読み取り+上書き書き込みです。 環境 windows2000 "an http daemon" linux (infoseekフリースペース) apache

    • ベストアンサー
    • Perl
  • ファィルの削除直後に作成したファィルにデータが書き込まれません。

    配列@arryの要素にデータが入っているとします。 (1)最初に「data.txt」が存在していない場合 open(out,">>data.txt"); foreach(@arry { print out "$_\n"; }; close(out); で、配列のデータは書き込まれます。 (2)最初に「data.txt」が存在している場合 unlink "data.txt"; open(out,">>data.txt"); foreach(@arry) { print out "$_\n"; }; close(out); }; close(FILE); これだと、「data.txt」は作成されますが、 空のファイルで、データは書き込まれません。 unlink "data.txt";以降がない場合は、確実に ファィルは削除されたままです。 一度削除後にデータを書き出したいのですが、教えてください。

    • ベストアンサー
    • Perl
  • 文字の置換がうまくいかない

    ********** test.txt ************* $first = "abc"; $last = "xyz"; ********************************* ********** change.txt *********** $first $firstaaa $last ********************************* という2つのテキストファイルがあったとして、 open(IN,"test.txt"); @data = IN; close IN; open(A,"change.txt"); while(<A>){$a_data .= $_} close A; foreach (@data) { if(/(\$[a-zA-Z_]+)[\t\s]*=[\t\s]*"(.+)"[\t\s]*;/){ my $name = $1; my $value = $2; print "$name<br>"; #$nameに何が入っているか表示 $a_data =~ s/$name/$value/g; } } としても、change.txtの$firstや$lastがabcや、xyzに置換されないのですが、なにがいけないのでしょうか?print "$name<br>";のところではちゃんと$firstと$lastという風に出力されています。$a_data =~ s/$name/$value/g;を$a_data =~ s/\$first/$value/g; と変えると、ちゃんと$firstだけ置換されました。 なにか心当たりがある方、よろしくお願いします。

    • ベストアンサー
    • Perl
  • perlのDigest::MD5;でのMD5算出が異なる

    perlのDigest::MD5;でのMD5算出が異なる 下記、スクリプトをレンタルサーバ上と、WindowsOS上で走らせてみたところ、おなじファイルにも関わらず、MD5が異なります。 何故でしょうか? #!/usr/local/bin/perl use strict; use warnings; use Digest::MD5; my $file = 'test.zip'; my $ctx = Digest::MD5->new; open my $fh, "<$file"; $ctx->addfile($fh); my $md5 = $ctx->hexdigest; close($fh); open my $fh2, ">>md5.txt"; print $fh2 "$file $md5\n"; print "$file $md5\n"; close $fh2;

    • ベストアンサー
    • Perl

専門家に質問してみよう