【Webプログラミング - Code.008】CGI(Perl)ファイル処理 その1:「ファイルを読む」

   Code.008                                                 2002年12月1日発行
■━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━■
                           【 Webプログラミング 】

                       〜 猫的プログラマーとその軌跡 〜
■━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━■

              ▼毎週月曜日に配信しています。
              ▼等幅フォントでご覧いただくとキレイに見えます。
              ▼登録・解除はこちらから可能です。
                < http://www.ichikoro.com/webp/ >
                  ※ぜひお友達にもご紹介ください(^^)/


こんにちは、編集者の勝部です。

先週、ニュースの中で一番心に残ったのはスクウェアとエニックスの合併
でした。事実上スクウェアは会社としては解散のようです。ファイナルファ
ンタジー(以下FF)が初めて世に出たのが1987年のまさにファミコン全盛期。
私がまだ小学生のころでした。

それから15年あまり、ゲーム業界の進歩とともに成長してきた世代としては
感慨深い物があります。エニックスは就職活動の際、資料請求から断られた
経緯があり、ハッキリ言って大嫌いなのですが(笑)、期待を裏切らない、胸
を熱くさせる作品を作って欲しい、そう強く思いました。

  ・スクウェアとエニックスが合併(11/26)
    http://www.watch.impress.co.jp/game/docs/20021126/square.htm

  ・スクウェア・エニックス、戦略説明会を開催(11/29)
    http://www.watch.impress.co.jp/game/docs/20021129/es.htm

というわけで、今週も行ってみましょう〜。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 CGI(Perl)ファイル処理 その1:「ファイルを読む」
──────────────────────────────────────
今回から最初にミッション(問題)を決めて、
それを解いて行くことにします。

今回のポイントは「ファイルからデータを読むこと」です。



    Mission : ファイル内のデータを並べ替えて表示せよ
    ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
        市内のレンタルビデオ店を営むY氏は、頭を抱えていました。10年近く前から
        のシステムをそのまま使用しているため、新規に出店しようとしている店舗と
        データの連携が出来ないのです。かといって新しく作り直すには資金も厳し
        い状態。

        そこで、個人的にホームページを運営していた経験のあるY氏は、インターネ
        ットで情報を共有できないか検討し始めたのです。まずは実験的に返却が遅れ
        ているユーザーを抽出するCGIを作り始めたのでした。

            ○問題
                以下のデータから未返却の会員だけを抽出し、延滞金の
                大きい順に表示せよ。

            ○データ
                A10000,山田,8000,1
                A23000,山本,9000,0
                A50000,田中,8000,1
                A51235,鈴木,12000,0
                A51240,五十嵐,7000,1
                A51250,武者小路,3000,0

        データの項目は左から「会員No」「氏名」「延滞金(円)」「返済フラグ」。
        返済フラグは「1:返済済み 0:未返済」となります。
        ファイル名は "list.csv" です。


ファイルから読み込んだデータを並べ替えて表示すると言うのは頻繁に行う
処理の一つです。さぁY氏はどんなプログラムを作ったのでしょう?


───────
   ソース
───────
;#
;#はよ返せ〜CGI
;#

use strict;
use CGI qw(:cgi);

package main;
{
    my @hensai;            #未返済者の情報を入れる配列
    my $buff;
    my $key;

    #-----------------------------------------#
    #              ファイルを開く             #
    #-----------------------------------------#
    open(DAT, "list.csv") or die("Can not open file : ($!)");

    #-----------------------------------------#
    #        ファイルからデータを取り出す     #
    #-----------------------------------------#
    while( $buff = <DAT> ){         #ファイルから一行読み込み、$buffに格納
        chomp $buff;                #最後が改行なら削除する

        #-- 各項目に分割する --#
        my ( $no, $name, $money, $flag ) = split(/,/, $buff);

        #-- $flagが未返済なら配列に格納 --#
        if( $flag == 0 ){
            my $str = join(",",    $money       #残金と名前、会員Noを一つの文字列に
                                    , $name
                                    , $no   );
            push(@hensai, $str);                #配列に入れる
        }
    }

    #-----------------------------------------#
    #             ファイルを閉じる            #
    #-----------------------------------------#
    close(DAT);


    #-----------------------------------------#
    #            並べ替えて表示する           #
    #-----------------------------------------#
    print header("text/plain");
    foreach $key (sort{ (split(/,/,$b))[0] <=> (split(/,/,$a))[0]  } @hensai){
        my ( $money, $name, $no ) = split(/,/, $key);

        printf("%8d円 %s(%s)\n", $money, $name, $no);
    }


    exit(0);
}

───────
    解  説
───────
今回からファイルの扱い方について解説いたします。

    ○ファイルを開く
        まずは以下の部分をご覧ください。

>            #-----------------------------------------#
>            #              ファイルを開く             #
>            #-----------------------------------------#
>            open(DAT, "list.csv") or die("Can not open file : ($!)");

        その名の通りopenは「ファイルを開け」という関数です。

            open(ファイルハンドル名, ファイルのパス(名前));

        という書式になります。
        ファイルのパスは絶対パス(/home/user/htdocs/test.dat)、相対パス(../test.dat)
        のどちらでも大丈夫です。


    ○ファイルから情報を読み出す
        開いたファイルは、「ファイルハンドル」を操作することで
        情報を取り出せたりします。このプログラムで言うと「DAT」です。

>            #-----------------------------------------#
>            #        ファイルからデータを取り出す     #
>            #-----------------------------------------#
>            while( $buff = <DAT> ){            #ファイルから一行読み込み、$buffに格納

        この中で

>            $buff = <DAT>

        の部分に注目です。
        こうすることでファイルから一行取り出せます。

>            $buff1 = <DAT>;
>            $buff2 = <DAT>;

        とすれば、$buff1には1行目が、$buff2では2行目が取得できます。
        さらに

            @buff = <DAT>;

        と配列を指定した場合は、ファイルの内容を「全て」得ることができます。
        ただあまり大きなファイルに対して使うとメモリを激しく消費しますので
        注意が必要です。


    ○ファイルを閉じる
        ファイルが開ける個数には限界があります。
        また開いたままというのは、お行儀が良いとはいえません。
        そこで必要が無くなったファイルは閉じてやります。

>            #-----------------------------------------#
>            #             ファイルを閉じる            #
>            #-----------------------------------------#
>            close(DAT);

        close関数に、閉じたいファイルのファイルハンドルを指定します。


───────
   次回予告
───────
Y氏は、またまた頭を悩ませていました。
このままだと情報を読み出すだけです。
お客さんが返却に来たり、情報を新しく更新することができません。


そこで、次回はファイルに書き出す方法を紹介したいと思います。


───────
  分からない
───────
いまいちよく分からない場合は、以下へれっつらごー。

  ・サポートBBS
    このメルマガ専用のサポート掲示板です。
    疑問などがあったら、お気軽に書き込んでやってください(^^)/
      http://www.ichikoro.com/webp/bbs/

  ・CGIプログラミングML
    CGIなどWebに関する話題を繰り広げるメーリングリスト。
    このメルマガとは関係ありませんので発言時は注意を。
      http://www.ichikoro.com/cgi/ml/


───────
  前回の訂正
───────
前回のメルマガで誤植がありました。
paramメソッドのサンプルに

> #ヘッダ出力
> $q->header();

とある部分は

> #ヘッダ出力
> print $q->header();

の間違いです。
上記の間違いが、合計三ヵ所あります。
大変申し訳ございませんでした。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
                           編    集    後    記
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

バックナンバーのページを新しく作り直しました。
見逃した号がある方はコチラからどうぞ!

    ・バックナンバー一覧
        http://www.ichikoro.com/webp/bktitle/
            まぐまぐよりも見やすいかな!?


さて今週からはじまったミッション性の解説。
例えば「ランダムに一行を取り出す」「ファイルを逆順に取り出す」など、
取り上げて欲しい処理があったらぜひお寄せください(^^)/

    mm-webp@ichikoro.com

それでは簡単ですが今回はこのへんで。
また来週お会いしましょう (^-^)/~~
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

                   【 Webプログラミング Code Sample 】

                    発  行 : ichikoro.com
                発行責任者 : 勝部 麻季人
                              < katsube@ichikoro.com >
                 Webサイト : < http://www.ichikoro.com/webp/ >
            お問い合わせ先 : < mm-webp@ichikoro.com >

                            Powerd by まぐまぐ
    All Right Reserved, CopyRight(C) 2001 Webプログラミング Code Sample
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■