<苦肉の策、配列をリングみたく使ってみた> こんにちは、Ken3です。 今回は、 テキストファイルのデータを逆順に読んでみたくって、 チャレンジしたけど、うまく行かなかった話です。 おい三流プログラマー、うまく行かない話をメルマガにするの? ええ、笑ってもらおうと思って。 (ホンネは、途中まで書いてて、出来ないことに気が付いて方向転換です(笑)) たいした話じゃないので、あまり期待しないでね。 /* * 1.やりたいこと */ キミは今日、何?やりたいの? (まず、要望をヒアリングかな) test008.txt ( http://www.ken3.org/cgi-bin/test/test008.txt ) に時刻と評価が下記のように書かれています。 2002/12/05 8:11:04 , 満足 2002/12/05 8:14:12 , 普通 2002/12/05 15:53:28 , 満足 ・ ・ ・ 2002/12/07 15:36:54 , 満足 2002/12/07 15:56:49 , 満足 2002/12/07 15:57:22 , 不正なパラメーターです とテキストファイルがあって、 これを表示するプログラム、をいろいろと作ってました。 そのまま表示 http://www.ken3.org/cgi-bin/test/test010-2.asp 5個単位で区切る http://www.ken3.org/cgi-bin/test/test018-1.asp 行番号を付ける http://www.ken3.org/cgi-bin/test/test019-1.asp この処理で共通しているのが、 頭からファイルを1行読んで、 行番号を付けたり、5個単位を判断して線を引いたりと、 登録順(ファイルの上から順)の処理でした。 よくある話で、最近の10件を知りたい、、、 なんて話がありますよね。 今回の要望は、最近の(最新の)10件を表示してみたい。 そんなの後ろから1行単位で読んで戻ればいいんだろ、簡単ジャン。 ほんと、サスガ三流と言ってもプログラマーさんだね、よろしくです。 /* * 2.ウソだろ?テキストファイルにランダムアクセスできない?(戻れないの?) */ 一般的な考え方として、 ファイルポインタを一行戻しながら読み、 (一行戻してから読み、2行戻すと1つ前に行くのかなぁ) を 繰り返せばいいのかなぁと安易に考える。 ファイルポインタを移動させるような命令を探してみる。 えっ、無いのもしかして? SkipLineメソッドってのあるから、 .SkipLine -2とかできないのかなぁ。 残念、できないみたいだ。 ファイルへランダムにアクセス可能か、調べないと。 もしかして、テキストストリームじゃダメだけど、 ほかの方法があるかもしれない。 今回は、プログラムでかわす方法を考えるか、、、 /* * 3.配列をリング的に使う */ リングって映画、怖いらしいねぇ。 私も知ってればいろいろと例を出せるけど知らないからなぁ、 じゃなくって、配列にデータをリング上に入れるイメージで処理してみます。 ソースを見る前に、イメージはリング(円)です。 円だったらサークルじゃないの? って思うけど、どうなんだろう。 まぁイイヤ。 で、下記が小手先技で最新10件を表示したソースです。 -- test023-1.asp <%@LANGUAGE=VBScript%> <html> <head> <title>配列をリング状に使う</title> </head> <body> <h2>配列をリング状に使う</h2> test023-1.asp<br> 配列をリング状に使って、最新の10件を表示した<br> <hr> <% Call DATA_READ() '読みこみ表示関数をコール%> <hr> 終了です。<br> <A HREF="test008.txt" TARGET="_blank">元データtest008.txtを見る</A><br> </body> </html> <% '気分で関数化して、外側に出してみた Sub DATA_READ() 'FileSystemObjectを生成します Set objFS = Server.CreateObject("Scripting.FileSystemObject") 'test008.txt を読取専用モードで開く Set ts = objFS.OpenTextFile(Server.MapPath("test008.txt"), 1, True) Dim strBOX(10) '*1文字列のバッファを10個取る Dim nSETIndex '*2セット位置 nSETIndex = 0 'セット位置を初期化 'ファイルからデータを読む Do While ts.AtEndOfStream = False 'ファイルの終端になってない間ループ '*3ファイルからデータを一行を読みバッファにセット strBOX(nSETIndex) = ts.ReadLine '*4バッファのセット位置を調整する nSETIndex = nSETIndex + 1 'セット位置を+1する(次に移動) If nSETIndex = 10 Then '10になったら0に戻す nSetIndex = 0 End If Loop ts.close '使ったファイルは閉じようよ(もうファイルは使わないので) 'データの表示 For i = 1 To 10 '10回まわるよ '表示位置の調整 nSETIndex = nSETIndex - 1 'ポインタを1つ前にする If nSETIndex < 0 Then '0以下になったら9にする nSETIndex = 9 End If 'データの表示 Response.Write strBOX(nSETIndex) '配列のデータを表示 Response.Write "<BR>" '改行のタグを入れる Next End Sub %> ---- なんか複雑なことやってるよね。 そんなこと無いですよ。 ファイルアクセスの準備 ^^^^^^^^^^^^^^^^^^^^^^ 'FileSystemObjectを生成します Set objFS = Server.CreateObject("Scripting.FileSystemObject") 'test008.txt を読取専用モードで開く Set ts = objFS.OpenTextFile(Server.MapPath("test008.txt"), 1, True) いつもの、 FileSystemObjectを生成とテキストストリームをオープンしてます。 私は前回のソースをコピーで作成してます。 バッファを10個用意した ^^^^^^^^^^^^^^^^^^^^^^^^ Dim strBOX(10) '*1文字列のバッファを10個取る 読みこんだデータを入れるバッファを10個用意しました。 0123456789 って感じですかねぇ。 セットする位置を記憶する変数を用意する ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Dim nSETIndex '*2セット位置 nSETIndex = 0 'セット位置を初期化 配列へのセット位置を変数で管理したいので、1つ変数を用意。 初めは0で初期化してます。 ファイルからデータを読み、用意した10個のバッファにセット ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 'ファイルからデータを読む Do While ts.AtEndOfStream = False 'ファイルの終端になってない間ループ '*3ファイルからデータを一行を読みバッファにセット strBOX(nSETIndex) = ts.ReadLine '*4バッファのセット位置を調整する nSETIndex = nSETIndex + 1 'セット位置を+1する(次に移動) If nSETIndex = 10 Then '10になったら0に戻す nSetIndex = 0 End If Loop ここが1つのポイントで、 '*3ファイルからデータを一行を読みバッファにセット strBOX(nSETIndex) = ts.ReadLine 何をしてるか? 命令見るとnSETIndex番目の配列にデータをセット。 初めは0だから0番目にセットされてます。 で、セット後に、 '*4バッファのセット位置を調整する nSETIndex = nSETIndex + 1 'セット位置を+1する(次に移動) 次の位置に移動してます。 If nSETIndex = 10 Then '10になったら0に戻す nSetIndex = 0 End If ここがポイントで、10になったら0にセット位置を戻してます。 0123456789012.... とセットする位置が循環します。 13個データがある場合はループで、 0に1行目 1に2行目 ・ ・ 8に9行目 9に10行目のデータが入る、 カウンタnSETIndexが10になったら、0に戻る ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0に11行目 1に12行目 2に13行目 カウンターnSETIndexは次の3になっている でデータが終わる(3にセットする前でデータEnd) データが連続で、10個の配列を使いまわして代入されてるイメージ、 なんとなくわかりましたか? ファイルは用済み ^^^^^^^^^^^^^^^^ ts.close '使ったファイルは閉じようよ(もうファイルは使わないので) データは読み終わったので、閉めます。 データの表示 ^^^^^^^^^^^^ 'データの表示 For i = 1 To 10 '10回まわるよ '表示位置の調整 nSETIndex = nSETIndex - 1 'ポインタを1つ前にする If nSETIndex < 0 Then '0以下になったら9にする nSETIndex = 9 End If 'データの表示 Response.Write strBOX(nSETIndex) '配列のデータを表示 Response.Write "<BR>" '改行のタグを入れる Next 表示は10個なので、10回のループを作ってます。 配列の0から表示すると?ダメですよね、(11,12,13の並びになってしまう) 配列のカウンターを戻しながら表示したいので nSETIndex = nSETIndex - 1 'ポインタを1つ前にする で、3だったカウンターが2に戻ります。 0に11行目 1に12行目 2に13行目 カウンターnSETIndexは次の3になっている でセットは、終わってましたね。 無事13行目のデータが表示され、 次はカウンターが1となり12行目、 次は0で11行目、 −1となったところで、 If nSETIndex < 0 Then '0以下になったら9にする nSETIndex = 9 End If のIf文が活躍して、 nSETIndex = 9 10行目のデータ表示になり、 また1つ減ってnSETIndex = 8で9行目のデータ。 こんな簡単な仕掛けだったんですね ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ なんて、強がって言ってる割には、苦労したけど。 テストの表示は、↓で試してください。 http://www.ken3.org/cgi-bin/test/test023-1.asp 元データTEST008.TXTと確認すると、なんとか逆順で表示されてます。 今思えば、1から10までセットのほうが説明わかりやすかったかも、 循環でバッファ使ってるのは、 1、11、21...は(1) 2、12、22...は(2) ・ ・ ・ 10、20、30...は(10)にセット が、わかりやすかったかなぁ。まぁいいや。 *書き直せよな、読者がわかりやすいように。 /* * 4.終わりの挨拶 */ 今回は、 ・テキストストリームのポインタ前の行に戻せないの?(勘違いかも) ・配列をリング的に使う でした。 テキストストリームのポインタ前の行に戻せない と 思いこんで、深みにハマッタかもしれないし、 ホントに戻れないので、 今回みたいな小細工必要だったり、、、 そろそろDBかなぁやはり。 素朴な疑問あったら、気軽に、 メール、掲示板に書き込んでくださいね。 ASP、VBScript勉強中の三流プログラマーのKen3でした。
ここまで、読んでいただきどうもです。目的の情報が見つかったか?少々心配しつつ、、、
感想や質問・要望・苦情など 三流君へメッセージを送る。
下記のフォームからメッセージを送ることができます。
[三流君(TOP ken3.org へ戻る)]
/ [ASPで遊ぶ、失敗する]
/ [ASP記事 バックナンバー目次]
まぁ、基本はデータの受け取りかなぁ。
・[Form等を使用したデータのやり取り]・・・ASPと言っても、HTMLの入力フォームからデータを受け取ります。POSTやGETでやりとりを押さえますか。
次は、データの入出力 で ADOを使った(ADOで接続) と SQLの解説を少々
・[ADOでMdbファイルを使う]・・・MDBと接続して、簡単な追加・更新・削除を行った。
・[ADOでExcelと接続してみた]・・・.xlsと接続してSQLを使ってみた。
・[ADOでCSVと接続してみた]・・・.CSV テキストを読み出した。※更新・削除はできません
広告:
DBが使えるので、あまり使用しないけど、普通のテキストファイル処理
・[テキストファイル処理]・・・ファイルを開いて、書き込む。1行読み込みなどを軽く
VBScriptでFormat関数が無いなど、微妙にVBAと違うけど
[VBScript関数関係の説明]・・・少し、処理を書いてみた。
[その他処理サンプル]・・・あまり良いサンプル作れなかったけど。。。
何かの参考となれば幸いです。
[三流君(TOP ken3.org へ戻る)]
/ [ASPで遊ぶ、失敗する]
/ [ASP記事 バックナンバー目次]