ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Perl自習部屋コミュのファイルの読み込みについて。

  • mixiチェック
  • このエントリーをはてなブックマークに追加
 はじめて書き込みします。Perl歴半年、CGIに夢中でありますが、日曜プログラマーなのでそれほど成長なし!という感じです。
 
 今現在ファイルの開閉について勉強中です。
 掲示板などformからデータを受け取って処理をするという場合に、ログを作ることになると思うんですが、一つのファイル(.txt)とかにログを作って読み書きすることはできるようになったのですが、今つまづいているのは、ファイルをそれぞれ分けて複数個のファイルがディレクトリにある場合です。
 複数個あるファイルから、読み込んだ内容をHTML表示させるというものを作りたいと思っているのですが、なかなかうまくいきません。タイトルをクリックするとその内容のxxxx.txtを読み込んでHTML表示させるという簡単なことなんですが…。。。ファイルはタイトルごとに分かれていて、中には通常のように、(例えば)「タイトル<>日にち<>長い文章…云々かんぬん…。\n」と1行にまとめています。

opendir(DIR, "./datafile");
while (my $filename = readdir(DIR)) {
next if $filename eq '.';
next if $filename eq '..';
unshift(@indexlist,$filename);
}
closedir(DIR);

foreach $value (@indexlist) {
print "$value<br>";
}
 こんな感じでファイル名を読みとってリンクを作ろうと思うんですが、このディレクトリには.txtファイルがあって、上に書いたようにファイル中にタイトルが記入されてあるんです。
 ここから
open (TXT, "< $indexlist[0]);
$line = <TXT>;
close (TXT);
という風に読み込みができて、読み込んだものをsplitできるようになると思うのですが、何せ複数個のファイルをここから読む込むというアイディアが全然思い浮かばないんです。
opendir(DIR, "./datafile");
while (my $filename = readdir(DIR)) {
next if $filename eq '.';
next if $filename eq '..';
open (TXT,"< $filename");
$line = <TXT>;
print $line;
close (TXT);
}
closedir(DIR);
などとやってみたのですが、当たり前の話しですが、全然ダメでした。

 今のところファイル名に日本語でタイトルを仕込んでおくということでやっていますが、ファイル名に日本語はあまり入れたくないなぁと思っています。
 まだまだ初心者ですが、あまり特殊なことをやろうとしている気がしなんです。
 通常どんな風に皆様がやっているのか、是非お聞きしたいと思って書き込みました。よろしくお願いします!

コメント(12)

はじめまして。私もPerlの勉強をそこそこしています・・
ファイル名に全角文字を使うことは一般的によろしくないかと思うのですが、
タイトル名をクリックして読み込ませるようにしたい場合は、
データ管理用ファイルの中にタイトル名などのファイル情報を置くほうが良いかと思います。
例えば、サーバー上とやりとりする間は、認識用ファイル名(data001.txtのような形式)にして、
表示する際は、タイトル名などの情報ですね。
形としては、仮にkiroku.txtとします、このファイルに、記事データとタイトルとの関連付けをしておきます。
読み込む際は、その管理ファイルを元にサーバーとやりとりをします。

kiroku.txt
タイトル名1<>data001.txt
タイトル名2<>data002.txt

data001.txt
タイトル<>日にち<>本文

のような感じです。
タイトル名一覧表示の際、ファイルテスト(-e)などを使って、存在するかどうか調べて、存在しなければ非表示→管理ファイルからもファイル名を削除、とすれば問題ないかと思いますし、
逆にタイトルの追加のときは、例にあげられてますとおり、
readdirを使ってファイル名を取得し、そこに名前をつけて、管理ファイルに情報を保存する、と言うやり方のほうが良いかと思います。それはそれでまた、設定を付け加えないといけませんけど。。
でも、結構面倒な方法かと思います・・書いてて私も思いました、、ごめんなさい。
もっと良い方法があれば提案をお願いします。
opendir DIR , './datafile' or die $!;
my @indexlist = grep { /\.txt$/ } readdir DIR;
closedir DIR;

for (@indexlist) {
    open TXT , '<' . './datafile/' . $_ or die $!;
    my $line = <TXT>;
    @_ = split /<>/ , $line;
    print "$_[0]\n";
    close TXT;
}

眠い目でテキトーに書いてみた。
動かなかったらスマン
なるほど!forだ!foreachばっかり考えてました!
(また、ちゃんと書き込みします!!)
>さゆにゃん☆さん
 ありがとうございます。僕も最初はそれをやっていたんですね。でも一応僕が使うブログ(みたいなもの)ではなくて、沢山の人が沢山の文章を書くという感じで、後から編集したり、ファイル名が変わっちゃったり…で、テンテンコまいだったんです。こりゃCGIだな、と諦めて勉強をはじめて、ある程度の掲示板みたいなのは作れるようになったんですが、大量コンテンツを扱うようなことを考えてもみなかったんです。
 いや、でもタイトルを日本語でファイル名にするよりは全然ましですね。

>のさん
 ばっちりできました!ありがとうございます。勉強なります。
 でも全然意味がわからない部分もありです。暇な時におしえてください。
 
動いたか?
そりはよかったよかった。

でな、
for って書いたんだけど、あれは本来ならばforeachと書くべきところを省略してforって書いただけなんだ。
つまりforループのようだが実際perlクンはforeachループしているんだ。
でけました!

opendir(DIR, "./datafile");
while (my $filename = readdir(DIR)) { #while使うと自分でわかりやすいというだけです。のさんの正規表現はまだ勉強中であります!
next if $filename eq '.';
next if $filename eq '..';
unshift(@indexlist,$filename);
}
closedir(DIR);
for (@indexlist) {
open TXT, '<' . './datafile/' . $_ or die $!;
my $line = <TXT>;
@_ = split /\t/ , $line;
print "$_[0]: <a href=\"./datafile/$_\" class=\"title\" target=\"_parent\">$_[2]</a><br>";
close TXT;

 やたらと時間かかりました。
 と、言うことは、forをforeachって書いても全く同じ動きをするってことですよね?何だか全然わからん世界に入ってきました。省略可能なPerlって。。(泣)
 後は、.txtではなく.htmlファイルにリンクするようにしたら完成であります!お世話になりました!!
あ、そうだ。もし暇だったら教えてください。

open TXT, '<' . './datafile/' . $_ or die $!;
これ初めて見ました。これは、.で区切っているんですよね?
もう一つは、die $!です。これは、or &errorみたいな感じでファイルが見つからない場合なんかに実行される奴でしょうか?調べたんですが、$!がわかりませんでした。

僕が見たことある感じだと、
open (TXT, "< datafile"|| &error);
とかです。()なしでopenできるんですね。
> これは、.で区切っているんですよね?
文字列連結演算子で調べてください。

> ファイルが見つからない場合なんかに実行される奴でしょうか?
そうです。エラールーチンがあるかわかんなかったので、dieを使いました。
やはりopenエラーでエラーを吐かないとどこで躓いたのかわからなくなりますよ。

> $!がわかりませんでした
特殊変数でググってみてください。
$!の他にもためになる特殊変数が見つかりますよ。

> ()なしでopenできるんですね。
そう
foreachをforと省略してみたり、
()を省略してみたり
とにかくタイプするのがマンドクサイのですw

あと、
> print "$_[0]: <a href=\"./datafile/$_\" class=\"title\" target=\"_parent\">$_[2]</a><br>";
を
print qq|$_[0]: <a href="./datafile/$_" class="title" target="_parent">$_[2]</a><br>|;
って書けば、いちいち「"」をエスケープする必要はなくなるからね。
 全部、わかりました!ありがとうございます!
 文字列連結演算子、特殊変数…何せ、記号と専門用語がまだ結び付かないので調べるの大変でした。

.←前回これで調べても何も出てきませんでした。(泣)

qq||←これ、すばらしいです。使わせて貰います!
 ところで、foreach自体の読み込みを逆からってできるんでしょうか?(新しいファイル順に上から表示できるようにしたい、ということなんです。)
 調べてみたけど、読み込みの昇順・逆順みたいなことについての解説っていうのが全然見あたりません。(ということはたぶん不可能)foreach、whileなんかで$_を使うと基本的には前から順に…ということになりますよね?
 以前はtempファイルなんかに一時保存して、ということをやっていましたが…。。

open (DATA, "< $datafile");
while (<DATA>) {
print TMP $_;
}
close (DATA);
close (TMP);
rename ($tempfile, $datafile);
…みたいな。。。
 あるいは、ソートし直して表示という方がいいんでしょうか?
 明日日曜なので、こちょこちょまたイジってみます。
これまでかいたやつを活かすなら

foreach (reverse(@indexlist)) {
#省略
}

で、どうですか?

ただこれだと、データが大きくなるとメモリにやさしくなさそうなのが気になりますが・・・。

小さいデータファイル(KB単位程度)ならそこそこ実用的だと思います。
rrrr re reverseできるんですね…(汗)。。。ちょっとびっくりしました。
 やすさんありがとうございます。やってみます!

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

Perl自習部屋 更新情報

Perl自習部屋のメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング