【Webプログラミング - Code.014】CGI(Perl)ファイル処理 その7:「DBMを使おう! 前編」

   Code.014                                                 2003年01月20日発行
■━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━■
                           【 Webプログラミング 】

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

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

こんにちは、編集長の勝部です。
特に意味は無いのですが、今回から編集長気取りです(笑)

さてさて、だいたい発行した直後くらいに読者の皆様からポツポツと
質問のメールをいただきます。リアクションがあるというのは非常に
うれしいのですが、メールの中にはなかなかするどい突っ込みをいた
だくことも多いのです。

というわけで個別に返信するよりも皆さんと共有したほうがいいんじ
ゃない?と思い立ち、Q&Aのコーナーを開始することにしました。
皆様からのご意見やご質問などお待ちしております(^^)/


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 CGI(Perl)ファイル処理 その7:「DBMを使おう! 前編」
──────────────────────────────────────
今回はDBMを『使わない』方式のCGIをご紹介します。
テキストファイルを上から順番に比較しながら見つける方法です。


    Mission : 郵便番号から住所を調べるCGIを作れ
    ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
        ○問題
            7桁の郵便番号を入力すると、その住所を表示する
            CGIを作成せよ。

            なお、郵便番号のデータは郵政事業庁が公開している
            データを使用すること。
            http://www.post.yusei.go.jp/newnumber/down.htm
              ※どの都道府県でもデータ形式は同じです。
                 一番下の「全国一括」で日本の全てを手中に
                 収めることができます(笑)


ダウンロードしたデータは使用しない項目が大量にあるので、
必要な項目だけを取り出しファイルに保存する作業を最初に
行います。

以下のプログラムを必要な箇所を訂正し実行してください。
  ※共用サーバをお使いの場合は、
    出来るだけローカル環境で行っ
    てください。


───────
  データ変換
───────
#!/usr/bin/perl

;#
;#郵便番号データから必要なデータだけ抜き出す。
;#

use CGI::Carp qw(fatalsToBrowser);       #エラー時にブラウザへ表示

#-------------------------------------------------#
#                ▼ココを設定する▼               #
#-------------------------------------------------#
#■ダウンロードしたファイル
$dat  = "KEN_ALL.CSV";

#■変換後のデータを記録するファイル
$file = "KEN_ALL_CONV.CSV";

#-------------------------------------------------#
#                   ▲ココまで▲                  #
#-------------------------------------------------#

#--------------------------#
#           変換開始       #
#--------------------------#
open(DAT, $dat)  or die("Can not open file:$dat ($!)");
open(OUT, ">$file") or die("Can not open file:$file ($!)");
while(<DAT>){
    chomp;
    my ( $post_cd, $ken, $addr1, $addr2 ) = (split(/,/))[2,6,7,8];

    #-- ダブルコーテーション削除 --#
    $post_cd =~ s/"//g;
    $ken     =~ s/"//g;
    $addr1   =~ s/"//g;
    $addr2   =~ s/"//g;

    print OUT join(",", $post_cd, $ken, $addr1, $addr2);
    print OUT "\n";
}
close(DAT);
close(OUT);


#--------------------------#
#   処理終了のメッセージ   #
#--------------------------#
print "Content-type: text/html\n\n";
print "<H2>OK</H2>\n";
print "データを変換しました\n";

exit(0);

__END__




上記を実行し無事にファイルが作成できたら、
今度は以下のソースを動かしてみましょう。
  ※データファイル名の部分だけ確認してください。


───────
 郵便番号検索
───────
#!/usr/bin/perl

;#
;#郵便番号検索CGI
;#

#----------------------------------------------------------------------#
#                            モジュール                                #
#----------------------------------------------------------------------#
use strict;                              #コーディングを厳格化
use CGI qw(:cgi);                        #フォームデータ取得
use CGI::Carp qw(fatalsToBrowser);       #エラー時にブラウザへ表示


#-------------------------------------------------#
#                   ▼ココを設定▼                #
#-------------------------------------------------#
#■データファイル(変換済みの物)
use constant DAT_FILE => "KEN_ALL_CONV.CSV";

#-------------------------------------------------#
#                   ▲ココまで▲                  #
#-------------------------------------------------#


#======================================================================#
#                           メインルーチン                             #
#======================================================================#
package main;
{
    my $search_flag = 0;           #検索処理を行ったか?
    my $hit_flag    = 0;           #検索した結果見つかったか?
    my $addr        = '';          #表示用の住所を格納する
    my $q           = new CGI();

    #-----------------------------------#
    #              引数取得             #
    #-----------------------------------#
    my $post_cd = $q->param("post_cd");    #郵便番号

    #-----------------------------------#
    #             ヘッダ表示            #
    #-----------------------------------#
    $| = 1;
    print $q->header( -type    => "text/html",
                      -charset => "Shift_JIS" );
    print_header();


    #-----------------------------------#
    #              検  索               #
    #-----------------------------------#
    if( $post_cd =~ /^([0-9]{7,8})$/ ){     #入力が正しければ検索

        #----------------------------#
        #         検索開始           #
        #----------------------------#
        $search_flag = 1;                   #検索フラグを立てる
        open(DAT, DAT_FILE) or die("Can not open file $!");
        while(<DAT>){
            chomp;
            my ($cd, $ken, $addr1, $addr2) = split(/,/);

            if( $post_cd eq $cd ){          #入力された郵便番号と一致するか
                $hit_flag = 1;              #一致すればヒットフラグを立てる

                #-- 表示用の住所を作成 --#
                $addr = $ken . $addr1 . $addr2;
                last;
            }
        }
    }


    #-----------------------------------#
    #             結果表示              #
    #-----------------------------------#
    if( $hit_flag ){
        #-- ヒット --#
        print "<H3>〒$post_cd $addr</H3>\n";
    }
    elsif( $search_flag ){
        #-- ハズレ --#
        print "<H3>No Hit</H3>\n";
    }
    else{
        #-- 検索しなかった(入力ミス、初期起動時) --#
        ;
    }


    #-----------------------------------#
    #             フッタ表示            #
    #-----------------------------------#
    print_footer();

    #-----------------------------------#
    #              正常終了             #
    #-----------------------------------#
    exit(0);
}


#--------------------------------------------------------------#
#■ヘッダ表示
#    内容:ヘッダ部分のHTMLを表示する
#    引数:なし
#  戻り値:なし
#--------------------------------------------------------------#
sub print_header{
    print <<"END_OF_HTML";
<HTML>
<HEAD>
<META http-equiv="Content-type" content="text/html; charset=Shift_JIS">
<TITLE>郵便番号検索</TITLE>
<STYLE type="text/css"><!--
    FORM {
        margin: 0px;
    }
-->
</STYLE>
</HEAD>
<BODY bgcolor="#FFFFFF">
<FORM>
    郵便番号:<INPUT type="text" name="post_cd" size="10"><INPUT type="submit" value="検索"><BR>
    <SMALL>※半角数字7桁。ハイフン('-')を入力しない。</SMALL>
</FORM>
<BR>
END_OF_HTML

}


#--------------------------------------------------------------#
#■フッタ表示
#    内容:フッタ部分のHTMLを表示する
#    引数:なし
#  戻り値:なし
#--------------------------------------------------------------#
sub print_footer{
    print <<"END_OF_HTML";
<BR>
<HR>
<DIV align="right">All Right Reserved, CopyRight (C) 2003
<A href="http://www.ichikoro.com/webp/" target="_blank">Webプログラミング</A>
</DIV>

</BODY>
</HTML>
END_OF_HTML
}

__END__



───────
   実行方法
───────

(1)以下のページから郵便番号のデータをダウンロードし、
  解凍します。どの都道府県でもOKです。

        http://www.post.yusei.go.jp/newnumber/down.htm

(2)テキストエディタ(メモ帳やSimpleText)などで変換プログラムを
   保存してください。適当な名前(xxxx.cgi)でOKです。
   ダウンロードしたファイル名、変換後のファイル名の部分を
   修正し実行します。

(3)データファイルが出来たことを確認します。
   中を開くと下記のようなデータが入っているハズです。

        0600000,北海道,札幌市中央区,以下に掲載がない場合
        0640941,北海道,札幌市中央区,旭ケ丘
        0600041,北海道,札幌市中央区,大通東
        0600042,北海道,札幌市中央区,大通西(1〜19丁目)
        0640820,北海道,札幌市中央区,大通西(20〜28丁目)

(4)検索プログラムの方を、テキストエディタなどで保存します。
   これもファイル名は適当でかまいません。同じようにデータ
   ファイルの指定だけします。

(5)郵便番号を検索してみます。


CGIの詳しい実行方法については Code.001 をご参照ください。
http://www.ichikoro.com/webp/bk/00046/


───────
   解  説
───────

特別目新しい技は使っていません。
というわけで今回は説明を割愛します。

実行&ソースを読んでください。


───────
   次回予告
───────
全く同じ事を今度はDBMを使用するとともに、
パフォーマンスの測定もやってみましょう〜。


───────
   配信予定
───────
ファイル処理編の配信一覧です。

    ・CGI(Perl)ファイル処理 その1:「ファイルを読む」
      http://www.ichikoro.com/webp/bk/00053/
    ・CGI(Perl)ファイル処理 その2:「ファイルへの書き込み」
      http://www.ichikoro.com/webp/bk/00054/
    ・CGI(Perl)ファイル処理 その3:「ファイルロック:flock 前編」
      http://www.ichikoro.com/webp/bk/00055/
    ・CGI(Perl)ファイル処理 その4:「ファイルロック:flock 後編」
      http://www.ichikoro.com/webp/bk/00056/
    ・CGI(Perl)ファイル処理 その5:「ファイルロック:mkdir編」
      http://www.ichikoro.com/webp/bk/00057/
    ・CGI(Perl)ファイル処理 その6:「ディレクトリ操作」
      http://www.ichikoro.com/webp/bk/00058/

    ・CGI(Perl)ファイル処理 その7:「DBMを使おう! 前編」<<今回
    ・CGI(Perl)ファイル処理 その8:「DBMを使おう! 中編(DBM使用)」
    ・CGI(Perl)ファイル処理 その8:「DBMを使おう! 後編(ロック)」

取り上げて欲しいテーマやご意見・ご要望はぜひ以下
までおよせください。

    ・BBS
      http://www.ichikoro.com/webp/bbs/

    ・メール
      mm-webp@ichikoro.com


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ここが知りたい! WebプログラミングQ&A
──────────────────────────────────────

    Q. Code13でアクセス制限した方がいいと書いてありましたが、
       どうやってすればいいのでしょうか?

    A. 簡単に行うならBASIC認証で。



前回、実行方法のところに

> ★注意!(必読)
>  全ての人に公開されたサーバ上で実行するのは非常に危険です。
>  アクセス制限を設けるか、ローカル上で実行してください。

と書いたところ、数名の方からメールをいただきました。
フォローもいれずにサクッと書きすぎ(^^;

    ・詳しくはコチラ(前回のメール)
      http://www.ichikoro.com/webp/bk/00058/

で、本題です。
Webサーバの種類がApacheの場合で.htaccessが使用できる場合、
以下のページを参考にしてください。
    ※IISの説明は割愛

    ・基本認証でアクセス制限(AllAbout)
      http://allabout.co.jp/computer/hpcreate/closeup/CU20020910A/
        ※telnetが使えるか、自分のマシンにApacheをインストール
          などしてパスワードの設定ファイルを作成する必要があり
          ます。

もしBASIC認証が使えない場合は、

    ・CGIのファイル名を暗号のようにする。
      例えば Avrt1257.cgi など。
        ※ディレクトリを叩くと、ファイル名の一覧が
          出るなんてことの無いように(^^;

    ・JavaScriptなどで簡易的な認証をする。
      http://www.google.co.jp/search?q=JavaScript+%83A%83N%83Z%83X%90%A7%8C%C0
        ※見破られる可能性大です。
          おすすめできません。

といった代替え手段も考えられます。


しかし、前回(Code13)のCGIをキチンとした認証を行わずに実行するのは
オススメできません。というかしないでください。非常に危険です。共用
サーバの場合、あなた以外の人に迷惑をかけてしまう可能性もあります。
可能な限りローカル環境で動かしてください。
    ※じゃぁ公開すんなという話もありますが(^^;


    ・自宅マシンWWWサーバ化計画(Windows向け)
      http://www.kent-web.com/www/

    ・Mac OS Web共有
      http://www.apple.co.jp/internet/pws/
        ※概要の説明のみ


また一部のISP(プロバイダ)では、認証機能を無料(あるいは有料)で提供
しているところもあります。こちらもご確認ください。


    ★募集中!
      Webプログラミングではこのコーナーで聞いてみたいご質問を
      受け付けております。メルマガで取り上げた内容と違っても
      OKです。お気軽にお寄せください。

              mm-webp@ichikoro.com
              (かつべへダイレクトに届きます)

───────
  分からない
───────
いまいちよく分からない場合は、以下で聞いてみることも
できます。

  ・サポートBBS
    このメルマガ専用のサポート掲示板です。
    勝部が(分かる範囲内で)ギモンにスパッとお答えします。
    メールで聞くより高速です。お気軽にお書き込みください(^^)/
      http://www.ichikoro.com/webp/bbs/

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


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
                           編    集    後    記
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
昨年末から教習所に通っています。
今回の目標は「普通二輪」。
日曜日に何とか第一段階を終了しました。
順調に行けば2月中旬には卒業できそうな感じです。


2輪には学生の頃からあこがれてまして、一時は教習所に通っていたのですが
途中でお金がなくなってしまい、本気でニッチモサッチモ行かなくなり断念
したのでした。

ところが昨年末にMotoGPの観戦に行ったのをきっかけに、どうしても
乗りたくなりました、ボーナスをつぎ込んでリベンジというわけです。

    ・MotoGPの話題はコチラ
      http://www.ichikoro.com/webp/bk/00047/


クルマ(4輪)と違い、教習が楽しいです。
通っているところがたまたまそうなのかもしれないですけど、
教官があんなに粘っこくなく、サッパリした感じです(笑)

朝からアクセルを吹かしつつ、風を切っているとホントに
気持ちいですね。時々教習中だというのを忘れそうになるくらい。

今年はツインリンクもてぎを一緒に走れるかな?
考えただけで背中が震える〜(笑)


また来週お会いしましょう! (^-^)/~~~
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

                   【 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-2003 Webプログラミング Code Sample
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■