GO BACK

Visual Basic教室 その7


「ファイルアクセスについて」


■ファイルの読み書きの基本手順


 ある程度本格的なプログラムを作成すると、「必要なデータをファイルに読み書きする」という作業が必要となってきます。今回は、そうしたファイルに関する基本について説明しましょう。

 とりあえず、ファイルの基本ということでテキストデータのファイルに絞って考えることにします。――Visual Basicでは、ファイルのアクセスには決まった手順を踏むことになっています。それは、以下のような形です。


1.Open命令を使ってファイルを開く。
2.読み書きする命令でファイルにアクセスをする。
3.使い終わったら、最後にClose命令でファイルを閉じる。


 これがファイル操作の一番の基本です。Visual Basicからファイルにアクセスするには、Openでファイルを開かなければいけません。そして使い終わったら必ずCloseします。これを忘れると、次にそのファイルを開こうとすると「既に開いています」とエラーが出たり、他のアプリケーションからファイルにアクセスできなくなったりします。必ずこの手順は守るようにして下さい。

 このOpenとCloseという命令は、以下のような形をしています。


Open 《ファイルパス》 For 《モード》 As 《ファイル番号》
《ファイルパス》で指定されたファイルを開く。これはファイルのパスを示すテキストで指定する。《モード》はファイルへのアクセスモードを示すもの(これは後述)。《ファイル番号》は、ファイルの管理番号で、プログラム内ではこの番号でファイルを管理する。このパラメータは番号の前に必ず#記号をつけて記述する。


Close 《ファイル番号》
指定したファイル番号のファイルを閉じる。


 これでファイルのOpen/Closeはできます。問題は、「読み書きする命令」ですね。これが、実はポイントになるのです。そしてこの読み書き命令は、 Open時のアクセスモードとも密接に関係してきます。




■テキストファイルの読み書き


 まあ、順番に説明していきましょう。まず、テキストファイルを保存する場合を考えてみましょう。これは、以下のような手順になります。


Open 《ファイルパス》 For Output As #1
Write #1, 《保存するテキスト》
Close #1


 これで完了です。意外と簡単でしょう? ――テキストファイルとしてファイルにデータを保存する場合、ファイルはOutputというモードでOpenします。そして、このモードで開かれたファイルにデータを保存するための命令が「Write」です。このWrite命令は、2つ目のパラメータのデータを1つ目のパラメータで指定したファイル番号のファイルに保存する働きをします。

 まあ、これはそう難しくはありません。次はファイルをテキストファイルとして読み込む場合です。これは、こんな手順になります。


Open 《ファイルパス》 For Input As #1
Input #1, 《取り込む変数》
Close #1


 書き込みとほとんど同じなのがわかりますね? 違っているのは、アクセスモードがInputになり、実行する命令が「Input」となっている点です。

 Input命令は、パラメータ1に指定したファイル番号のファイルからデータを読み込み、2番目のパラメータの変数に収める働きをします。ですから、この後で取り込んだ変数をコントロールなどに表示するなどしてやればいいわけです。「なぜ書くのはWriteなのに読むのはReadでなくてInputなんだ?」などいろいろ疑問なことはあるでしょうが(笑)、まあとりあえず基本的な命令と手順だけ頭に入れておいてください。

 では、実際に簡単なサンプルを作ってみることにしましょう。――まず、フォームの上にTextBoxを1つとCommandButtonを2つ作成して下さい。TextBoxは、MultiLineプロパティをTrueに、ScrollBarsプロパティを「2-垂直」に設定します。

 MultiLineというのは、複数行のテキストを扱えるようにするかどうかを設定するもので、これがFalseだと1行のテキストしか扱えません。またScrollBarsは文字どおりスクロールバーを表示するかどうかを示すもので、これを使って縦横のスクロールバーを表示できるのです。

 さてCommandButtonの方ですが、これはオブジェクト名を「ReadBtn」「WriteBtn」とそれぞれ変更しておきましょう。ついでにCaptionプロパティを「読む」「書く」と変更しておきます。

 以上の作業ができたら、2つのボタンにサブルーチンを割り当てます。作成するコードは以下で全てです。

Private Sub ReadBtn_Click()
  fname = "c:\My Documents\Test.txt"
  Open fname For Input As #1
  Input #1, str1
  Close #1
  Text1.Text = str1
End Sub

Private Sub WriteBtn_Click()
  fname = "c:\My Documents\Test.txt"
  Open fname For Output As #1
  Write #1, Text1.Text
  Close #1
End Sub

 これは、Cドライブの「My Documents」フォルダにある「Test.txt」というファイルにテキストを読み書きするサブルーチンです。起動したら、TextBoxに適当に文章を書いて「書く」ボタンを押してみましょう。「My Documents」フォルダに「Test.txt」ファイルが作成されます。そして「読む」ボタンを押せば、そのファイルのテキストを読み込んでTextBoxに表示してくれます。

 上記のサブルーチンを見れば、先に説明した基本手順をそのまま実行しているだけなのがわかりますね。ここでは読み込むファイルのパスにc:\My Documents\Test.txtというのを設定していますが、これを変更すればもちろん他のファイルも読み書きできます。




■コモンダイアログの利用法


 これで一応はテキストファイルの読み書きができるようになりましたが、まだまだ問題はあります。なにより「テキストファイルのパスを変数に用意しておくのでは汎用性がない」ということです。

 先のサブルーチンのように、読み書きするファイルのパスをサブルーチンの中に用意しておくのでは、他のファイルを読み書きできなくなっていまいます。また、指定したファイルが見つからなかった場合にエラーが発生する可能性もあります。

 ではどうすればいいか。まあ、TextBoxなどを用意して、そこにファイルのパスを書き込むようにしてもいいのですが、どうも「ファイルのパス」というのは非常にわかりにくいものです。開きたいファイルのパスをいちいち調べて書くのは面倒ですしね。

 通常、Windowsのプログラムではファイルを選択する場合、専用のオープン/セーブダイアログが呼び出され、そこでファイルを選択するようになっています。これは「コモンダイアログ」と呼ばれるものです。Visual Basicではこのコモンダイアログは利用できないんでしょうか?

 ツールボックスを見たところでは、それらしいコントロールは見当たりません。が、使えないというわけではありません。コモンダイアログは、Active Xコントロールとして用意されており、Visual Basic ver.5.0以降をインストールしているならばシステムに組み込まれている(はず?)です。

 これを使うには、「プロジェクト」メニューの「コンポーネント」を選びます。これで現れるダイアログは、そのプロジェクトで利用するコンポーネントを設定するためのものです。ここで「Microsoft Common Dialog Control 6.0(または5.0)」という項目を探して下さい。これがコモンコントロールのActive Xコントロールです。このチェックをONにしてダイアログを閉じると、ツールボックスに一番下にコモンダイアログのアイコンが追加されます。

 では、先ほど作成したフォームに、Common Dialogコントロールを1つ配置してみましょう。これも、Timerなどと同様に「見えないコントロール」です。コントロールを作成するとアイコンが表示されますが、これはプログラムを実行すると表示されません。

 では、先の2つのサブルーチンを、コモンダイアログを利用してファイルを選択するような形に書き換えてみましょう。

Private Sub ReadBtn_Click()
  CommonDialog1.ShowOpen
  fname = CommonDialog1.FileName
  If fname = "" Then Exit Sub
  Open fname For Input As #1
  Input #1, str1
  Close #1
  Text1.Text = str1
End Sub

Private Sub WriteBtn_Click()
  CommonDialog1.ShowSave
  fname = CommonDialog1.FileName
  If fname = "" Then Exit Sub
  Open fname For Output As #1
  Write #1, Text1.Text
  Close #1
End Sub

 これで完成です。実際に動かして動作を確認してみて下さい。ボタンをクリックすると、画面にファイルを選択するダイアログが現れます。キャンセルすればそのまま処理をせずに終わりますし、ファイルを選択したりファイル名を入力して開くと、ちゃんとファイルが読み書きされます。

 では、CommonDialogの働きを見てみましょう。例としてReadBtnのサブルーチンをチェックしてみます。

  CommonDialog1.ShowOpen

まず、CommonDialog1の「ShowOpen」というメソッドを呼び出しています。これは、オープンダイアログを画面に表示する働きをするものです。同様に、セーブダイアログを呼び出すときは「ShowSave」というメソッドを呼び出します。

 このメソッドを実行すると、画面にダイアログを呼び出し、ユーザーがファイルを選択したりファイル名を入力したりしてダイアログが消えるまで、一通りの処理を全てCommonDialogが行なってくれます。

  fname = CommonDialog1.FileName
  If fname = "" Then Exit Sub

 その後に、このような処理がありますね。これは、ユーザーが選択したり入力したファイルのパスを取り出し、キャンセルされた場合の処理を行なっている部分です。

 ダイアログでユーザーがファイルを選んだり入力したりすると、そのファイルのパスがCommonDialogの「FileName」というプロパティに設定されます。もしキャンセルをした場合には、このFileNameは空の状態になるのです。

 ですから、このFIleNameプロパティを変数に取り出し、これが空だった場合にはExit Subでサブルーチンを抜け出ているというわけです。

 これでファイルのパスが得られたなら、後は今までと同じです。Openでファイルを開き、InputやWriteしてCloseすればおしまい!です。意外と簡単ですね?




■テータベース的なアクセスの手法


 これで、単純にテキストを読み書きすることは可能になりました。が、ファイルにデータを読み書きするというのは、「長いテキストを1つ保存する」というような単純なものではありません。いくつもの値を読み込んだり保存したりといった作業が必要になることのほうが多いものです。

 通常、こうした複雑なデータのやり取りは「バイナリファイル」と呼ばれるファイルを使ってバイト単位でデータを読んだり書いたり…といった面倒で複雑な処理をしなければならないのですが、Visual Basicではもっと簡単に行なうことができます。テキストファイルをデータベース的に利用することが可能なのです。

 先に、InputやWrite命令を使った際、読み込む変数として1つだけ変数を用意しておきました。これを、カンマで区切っていくつもの変数を用意しておくと、それらのデータを続けて読み書きするようになります。例えば、

Write #1, str1, str2, str3

こんな形で実行すると、str1〜str3の3つの変数の値を続けてファイルに保存します。そしてそのファイルからデータを読み込むときに、

Input #1, str1, str2, str3

このようにすると、保存してあった3つの値がそれぞれstr1〜str3に収められるのです。ただのテキストファイルなのに、不思議ですね?

 この秘密は、保存したファイルの中身にあります。上記のWrite命令ような形で3つの値を保存したとしましょう。その保存したテキストファイルをノートパッドなどで開いてみると、面白いことがわかります。

 なんと、1つ1つの変数の中身がダブルクォート(")でくくられ、カンマ(,)で区切って記述されているのです。そしてInputされると、このカンマで区切ってあるデータを1つずつ読み込み、変数に収めていたのですね。

 また、Visual Basicでは1回のWrite命令を実行すると、データを記述した後を改行しておきます。ですから上記のようなWrite命令を何度も実行すると、3つの値が1行ずつ改行された形で書き出されるのです。実に頭がイイですねえ。

 この他にも、データベース的にテキストファイルを扱う場合、便利な機能がいくつかあります。ここで紹介しておきましょう。


Open 《パス》 For Append As 《ファイル番号》
アクセスモードを「Append」としてファイルを開くと、ファイルの末尾にデータを追記できるようになります。通常、Outputモードで開いてからWriteすると、データは全て上書きされてしまいますが、Appendでは元のデータを残し、その後に付け足すので、データを蓄積していく場合などに重宝します。


Line Input 《ファイル番号》, 《変数》
指定したファイル番号のファイルからデータを1行だけ読み込み変数に収めます。先に触れたように、Writeで書かれるデータは、1回ごとに改行して書き出されます。ですから、このLine Inputで1行ずつデータを取り出して処理することもできるわけです。

 では、データベース的にテキストファイルを扱うサンプルをちょっと作ってみましょう。これは、ちょっとだけ部品が多いので順番に作って下さい。

 まずTextBoxが6個必要となります。これは、それぞれ以下のようになります。


「Text1」「Text2」「Text3」――3つの各項目を入力するためのもの。それぞれ大きさを揃えておく。
「DataText1」「DataText2」「DataText3」――3つの項目のデータをそれぞれ改行して一覧表示するためのもの。3つともMultiLineをTrueにし、スクロールバーを表示させておく。そして大きさを揃えて並べて配置する。


 次に、3つのCommandButtonが必要になります。これは、以下のように設定します。


「SelectBtn」――ファイル選択用のもの。「ファイル選択」とCaptionを設定。
「ReadBtn」――ファイルからテキストを読み込むためのもの。
「WriteBtn」――ファイルにデータを追記するためのもの。


 最後に、CommonDialogを1つ作成して、フォームの部品は完成です。そしてできあがったら、3つのボタンにサブルーチンを記述します。

Private Sub SelectBtn_Click()
  CommonDialog1.ShowOpen
End Sub

Private Sub ReadBtn_Click()
  fname = CommonDialog1.FileName
  If fname = "" Then Exit Sub
  str1 = ""
  str2 = ""
  str3 = ""
  Open fname For Input As #1
  Do Until EOF(1)
    Input #1, s1, s2, s3, s4
    str1 = str1 & s1 & vbCrLf
    str2 = str2 & s2 & vbCrLf
    str3 = str3 & s3 & vbCrLf
  Loop
  Close #1
  DataText1.Text = str1
  DataText2.Text = str2
  DataText3.Text = str3
End Sub

Private Sub WriteBtn_Click()
  fname = CommonDialog1.FileName
  If fname = "" Then Exit Sub
  Open fname For Append As #1
  Write #1, Text1.Text, Text2.Text, Text3, Text
  Close #1
End Sub

 これは、3つの項目を持った簡易データベースです。完成したら、さっそく起動してみましょう。――使うときは、まず最初に「ファイル選択」ボタンを押してデータベースファイルを選びます。最初は新しいファイル名を入力しておきましょう。

 そして3つのTextBoxにテキストを書き込み、WriteBtnボタンを押します。これでファイルにデータが追記されます。何回かデータを書き込んだところで、ReadBtnをクリックしてみましょう。3つのデータがそれぞれまとめられ一覧表示されますよ。

 ここで実行しているサブルーチンはほぼ今まで説明したことで理解できるはずですが、ReadBtnがちょっとわかりにくいので、いくつか補足しておきましょう。 

  Do Until EOF(1)

 データの読み込みをする部分は、こんな形になっていますね? これは、「Do ~ Loop」という繰り返し構文です。この構文は、条件をチェックして繰り返しを実行するものです。

 これは、以下のような形をしています。

Do until/while 《条件式》
 ……繰り返す命令……
Loop

 Doの後に「until」と「while」という2つのものが用意されています。untilの場合は、その後の条件がTrueになったら繰り返しを抜け出ます。whileの場合は、条件がTrueの間繰り返し、Falseになったら抜け出ます。

 で、肝心の繰り返し条件ですが、ここでは「EOF(1)」というものが設定されています。これは、「指定したファイル番号のファイルを一番最後まで読み込んだかどうか」をチェックする関数です。この値がTrueならば、ファイルの最後まで読み込んだことを示します。

 ここでは「Do Until EOF(1)」となっていました。ということは、「ファイル番号1が最後まで読み込まれたら繰り返しを抜け出す」ということだったわけです。

 この「Do Until EOF(1)」というのは、繰り返しデータを読み込むときの慣用句といってよいでしょう。

    Input #1, s1, s2, s3, s4

 そして繰り返し部分でデータを読み込んでいるのがここです。…あれ、よく見ると変数が4つも書いてありますね? データは3つしかなかったはずです。これはどういうことなのでしょう?

 実をいえば、Writeで複数の項目を書き込んだとき、一番最後に「,」をつけて改行してしまうというクセ(?)があるのです。例えば「A」「B」「C」という3つのデータをWriteで書き込むと、


"A", "B", "C",


このようにファイルには書き込まれます。これは、読み込むときに「一番最後に何もないからっぽの項目がついている」と見なされてしまうのです。これは、どうもバグ臭い気がするのですが…。そのうち、修正されるかも知れませんね。

 というわけで、読み込むときは4つの変数におさめ、そのうち3つだけを使うようにしているのです。

str1 = str1 & s1 & vbCrLf
読み込んだ後で、データをそれぞれ別の変数の終りに付け足していますが、ここでは最後に「vbCrLf」というものをつけていますね。

 これは、改行コードを示す定数なのです。Visual Basicでテキストを&でつなぐとき、間を改行したいときはこのvbCrLfを使うのです。

 以上で、だいたいの流れはわかるかと思います。Visual Basicでは、テキストファイルの他にバイナリファイルなども扱えますが、とりあえずテキストファイルだけでも一通りのことができることはわかったでしょう。ファイル操作は実際にやってみないとなかなか難しそうに感じてしまいますから、それぞれでサブルーチンをアレンジしていろいろ試してみるとよいでしょう。


GO NEXT


GO HOME