連載:VB 6ユーザーのための
これならマスターできるVB 2005超入門

第8回 ファイル入出力をマスターしよう

羽山 博
2007/04/20
Page1 Page2 Page3 Page4

サンプル・プログラム11 − ランダム・アクセスでデータを読み出すには

 StreamReaderクラスを利用すると、いわゆる順アクセスでデータを読み出すことができる。先ほどの例では1行のデータを読み出すReadLineメソッドを使ったが、Readメソッドでは指定した文字数のデータを読み出すことができ、ReadToEndメソッドでは現在位置からファイルの末尾までを読み出すことができる。

 しかしながら、Seekメソッドを使ったランダム・アクセスはできない。ランダム・アクセスのためには、バッファ化された入出力ができるFileStreamクラスを使う必要がある。

■FileStreamクラスを使う

 利用するデータやフォームは先ほどのプログラムと同じものを使うこととしよう。プログラムの機能としてはあまり意味がないが、今度は9文字目から3文字分をデバッグ・ウィンドウに表示するコードを書いてみよう。

 学生番号を使って検索するわけではないので、テキストボックスはもはや使わないが、フォームはサンプル・プログラム10のものをそのまま使い、btnSearch.Clickイベント・ハンドラの中身だけを以下のように書き換えてみる。

Private Sub countNumber(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSearch.Click

  Dim fs As FileStream
  Dim buf(2) As byte
  Dim ec As System.Text.Encoding = System.Text.Encoding.ASCII

  fs = New FileStream("c:\Home\attend.log", FileMode.Open, FileAccess.Read)
  fs.Seek(9, SeekOrigin.Begin)
  fs.Read(buf, 0, buf.length)

  Debug.Print(ec.GetString(buf))

  fs.Close()
End Sub
リスト2 9文字目から3文字分を読み出すためのコード
  FileStreamクラスのオブジェクトを参照するための変数を宣言する。
  FileStreamクラスの新しいオブジェクトを作成する。引数にはファイル名、オープン・モード、アクセス・モードを指定する。
  Seekメソッドで、先頭から9文字(バイト)目に位置付ける。
  データを読み出し、bufというバイト配列に先頭から3バイト分入れる。
  バイト配列をASCIIコードとして文字列に変換し、デバッグ・ウィンドウに表示する。

 FileStreamクラスのオブジェクトを作成する方法は、StreamReaderクラスの場合とほとんど同じだが、ファイルのオープン・モードやアクセス・モードなどを指定する必要がある。

 オープン・モードは以下のいずれかを指定する。

内容
FileMode.Append ファイルの末尾に追加する。ファイルが存在しなければ新規作成
FileMode.Create ファイルを新規作成する。すでにファイルがあると上書きされる
FileMode.CreateNew ファイルを新規作成する。すでにファイルがある場合は例外(IOException)がスローされる
FileMode.Open ファイルを開く。ファイルが存在しない場合は例外(FileNotFoundException)がスローされる
FileMode.OpenOrCreate ファイルを開く。ファイルが存在しない場合は新規作成
FileMode.Truncate ファイルを開き、サイズを0にする
表3 オープン・モードの一覧

 また、アクセス・モードには以下の値が指定できる。

内容
FileAccess.Read 読み出しモードで開く
FileAccess.Write 書き込みモードで開く
FileAccess.ReadWrite 読み出し、書き込みのいずれも可能なモードで開く
表4 アクセス・モードの一覧

 あとは、Seekメソッドを使って読み出し位置を変更し、Readメソッドで必要なバイト数だけ読み出してやればよい。Seekメソッドに指定する位置は先頭が0であることに注意。また、2番目の引数には検索の開始位置を以下のように指定する。

内容
SeekOrigin.Begin ストリームの先頭
SeekOrigin.Current ストリームの現在位置
SeekOrigin.End ストリームの末尾
表5 Seekメソッドの第2引数で指定する開始位置

 なお、Visual Basicの配列を宣言するときに、()の中には要素数ではなくインデックスの最大値を指定することにも注意が必要だ。

Dim buf(2) As Byte

とすると、buf(0)からbuf(2)までの3つの要素が作られる。

■FileStreamクラスとStreamReaderクラスを組み合わせる

 FileStreamクラスのReadメソッドでは読み出されたデータはバイトの配列となっているので、System.Text.Encodingオブジェクトを使って文字列に変換する必要があり、取り扱いが若干面倒だった。

 一方、StreamReaderクラスでは読み出したデータは文字列や文字の配列として利用できるので、取り扱いが比較的ラクだが、ランダム・アクセスができない。あちらを立てればこちらが立たず……といった感じではがゆさを禁じ得ない。が、ちゃんと解決策はある。理屈は後回しにして、以下のようにコードを書き換えてみよう。

Private Sub countNumber(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSearch.Click

  Dim fs As FileStream
  Dim sr As StreamReader
  Dim buf(2) As Char

  fs = New FileStream("c:\Home\attend.log", FileMode.Open, FileAccess.Read)
  sr = New StreamReader(fs)
  fs.seek(9, SeekOrigin.Begin)
  sr.ReadBlock(buf, 0, buf.length)

  Debug.Print(buf)

  sr.Close()
  fs.Close()
End Sub
リスト3 9文字目から3文字分を読み出すためのコード
  StreamReaderクラスの新しいオブジェクトを作成する。引数にはFileStreamクラスのオブジェクトを参照する変数を指定する。
  Seekメソッドで9文字(バイト)目に位置付ける。
  StreamReaderクラスのReadBlockメソッドで、指定された文字数だけ読み出す。

 StreamReaderクラスのオブジェクトを作成するときには、ファイル名を指定してストリームを作ることもできるが、すでにあるストリーム(ここではFileStreamクラスのオブジェクト)を指定して、そこからデータを読み出すこともできる。そうすれば、FileStreamクラスのSeekメソッドを使って読み出し位置を決め、StreamReaderクラスのReadBlockメソッドなどを使って、指定した文字数を読み出すことができる*2

*2 わざわざFileStreamクラスと組み合わせずに、
sr.BaseStream.Seek(9, SeekOrigin.Begin)
というコードで読み出し位置を決める方法もある。実は、ファイル名を指定してStreamReaderオブジェクトを作成すると、BaseStreamプロパティはFileStreamオブジェクトとなっているので、FileStreamクラスのメソッドが使える。

 こうすれば、テキスト・ファイルもランダム・アクセスしやすくなるというわけだ。この考え方もなかなか実感がわかないかもしれないが、図4のようなイメージでとらえるといいだろう。


図4 FileStreamクラスとStreamReaderクラスの組み合わせ
StreamReaderクラスのオブジェクトを作成するときに、ストリームとしてFileStreamオブジェクトを指定することができる。こうすれば、ランダム・アクセスもできるし、文字列の扱いもラクになる。

 ファイルからの読み出しには、さまざまなバリエーションがあり、すべてを完全に網羅することはできないが、ここで説明した例を理解していれば、ほかの方法もヘルプやドキュメントを見ながら自分で書くことができるだろう。これまで読み出しの例ばかりだったので、最後に書き込みの例を1つだけ見ておこう。


 INDEX
  連載:VB 6ユーザーのためのこれならマスターできるVB 2005超入門
  第8回 ファイル入出力をマスターしよう
    1.サンプル・プログラム10 − テキスト・ファイルの検索プログラム
    2.テキスト・ファイルからデータを読み出せるようにするには
  3.サンプル・プログラム11 − ランダム・アクセスでデータを読み出すには
    4.サンプル・プログラム12 − ファイルに追加書き込みするには
 
インデックス・ページヘ  「これならマスターできるVB 2005超入門」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH