StreamReaderクラスを用いたテキストファイル読み込み、using構文によるファイルのクローズ、例外処理など、.NETにおけるテキストファイル読み込みの基本を解説する。
本稿は2003/06/13に初版公開、2008/08/14に改訂された記事を再改訂し、Visual Studio 2017でコードの動作検証、図版の追加、全般的な構成の変更などを行ったものです。
テキストファイルの読み込みは、今なおプログラミングにおける基本的な処理の一つである。
特定のトピックをすぐに知りたいという方は以下のリンクを活用してほしい。
テキストファイルの読み込みには、その目的や利用している.NET Frameworkのバージョンによって、さまざまな方法がある。適切な方法を選んでほしい。
テキストファイルの内容を読み込むには、まずファイルを開き、次にその内容を読み込み、最後にファイルを閉じる処理が必要になる。
ファイルを開くには幾つかの書き方があるが、Windowsで最も一般的に使用されているシフトJISのファイルを、ファイル名を指定して開くにはStreamReaderクラス(System.IO名前空間)を次のようにして使用するのが最も簡便だ。
StreamReader sr = new StreamReader(
"readme.txt", Encoding.GetEncoding("Shift_JIS"));
Dim sr As New StreamReader( _
"readme.txt", Encoding.GetEncoding("Shift_JIS"))
StreamReaderクラスには多くのコンストラクタが用意されているが、ここでは開くファイルと、そのファイルのキャラクタセットに対応したEncodingクラス(System.Text名前空間)のオブジェクトを指定するバージョンを使用している。この場合には、シフトJISに対応したEncodingオブジェクトを使用しているため、ファイルの読み込み時にはその内容がシフトJIS文字列で構成されているものとして取り扱われる(Encodingクラスについては、「TIPS:文字列をシフトJISとしてバイト列に変換するには?」などで解説している)。
続いてStreamReaderクラスのReadToEndメソッドを呼び出せば、ファイルの内容を全て1つの文字列に読み込むことができる。次のサンプルプログラムは、カレントディレクトリにあるシフトJISのファイル「readme.txt」を文字列に読み込み、それを画面に表示する。
// fread1.cs
using System;
using System.IO;
using System.Text;
class FileRead1 {
static void Main() {
StreamReader sr = new StreamReader(
"readme.txt", Encoding.GetEncoding("Shift_JIS"));
string text = sr.ReadToEnd();
sr.Close();
Console.Write(text);
}
}
// コンパイル方法:csc fread1.cs
' fread1.vb
Imports System
Imports System.IO
Imports System.Text
Class FileRead1
Shared Sub Main()
Dim sr As New StreamReader( _
"readme.txt", Encoding.GetEncoding("Shift_JIS"))
Dim text As String = sr.ReadToEnd()
sr.Close()
Console.Write(text)
End Sub
End Class
' コンパイル方法:vbc fread1.vb
ReadToEndメソッドでは、改行コードなども含めて全ての1つの文字列として読み込まれる。
StreamReaderクラスで開いたファイルは、そのCloseメソッドにより閉じておく必要がある。Openメソッド(StreamReaderクラスにはない)などで明示的にオープン処理を呼び出していないのにもかかわらず、Closeメソッドを呼び出すのは少し不自然さを感じるかもしれない。
StreamReaderクラスはIDisposableインタフェースを実装しているため(正確には親クラスのTextReaderクラスが実装している)、次のサンプルプログラムのように、Closeメソッドを呼び出す代わりにusingステートメントを利用することもできる(IDisposableインタフェースやusingステートメントに関しては「TIPS:確実な終了処理を行うには?」で解説している)。
// fread2.cs
using System;
using System.IO;
using System.Text;
class FileRead2 {
static void Main() {
string text = "";
using (StreamReader sr = new StreamReader(
"readme.txt", Encoding.GetEncoding("Shift_JIS"))) {
text = sr.ReadToEnd();
}
Console.Write(text);
}
}
// コンパイル方法:csc fread2.cs
' fread2.vb
Imports System
Imports System.IO
Imports System.Text
Class FileRead2
Shared Sub Main()
Dim text As String = ""
Using sr As New StreamReader( _
"readme.txt", Encoding.GetEncoding("Shift_JIS"))
text = sr.ReadToEnd()
End Using
Console.Write(text)
End Sub
End Class
' コンパイル方法:vbc fread2.vb
この場合には、usingステートメントの実行を終えたときに、自動的にStreamReaderクラスのDisposeメソッドが呼び出され、その中でCloseメソッドが呼び出されることになる。
以上2つのサンプルプログラムでは、開こうとするファイルが存在しない場合や、ファイルの読み取り中にディスクなどに何らかの障害が発生した場合には、例外が発生してプログラムの実行が中断してしまう。
実際のアプリケーションでは、このような例外発生時に備えて、次のような例外処理を記述しておく必要があるだろう。
// fread3.cs
using System;
using System.IO;
using System.Text;
class FileRead3 {
static void Main() {
string text = "";
try {
using (StreamReader sr = new StreamReader(
"readme.txt", Encoding.GetEncoding("Shift_JIS"))) {
text = sr.ReadToEnd();
}
Console.Write(text);
} catch (Exception e) {
Console.WriteLine(e.Message);
}
}
}
// コンパイル方法:csc fread3.cs
' fread3.vb
Imports System
Imports System.IO
Imports System.Text
Class FileRead3
Shared Sub Main()
Dim text As String = ""
Try
Using sr As New StreamReader( _
"readme.txt", Encoding.GetEncoding("Shift_JIS"))
text = sr.ReadToEnd()
End Using
Console.Write(text)
Catch exception As Exception
Console.WriteLine(exception.Message)
End Try
End Sub
End Class
' コンパイル方法:vbc fread3.vb
usingステートメントを使用していると、例外発生時にもファイルのクローズ処理が自動的に行われるため便利だ。
処理によっては、ファイル全体を1つの文字列として読み込むよりも、1行ずつ読み込んで文字列の配列とした方が扱いやすい場合がある。ファイルから1行読み込むには、ReadLineメソッドを使用すればよい。ReadLineメソッドは、StreamReaderクラスによりオープンされたファイルから1行だけ読み取り、内部の読み取り位置を1行分進める。読み取り位置がファイルの最後に達した場合にはnull(VBの場合にはNothing)を返す。
次のサンプルプログラムではファイルの行を読み込みながら、ArrayListクラス(System.Collections名前空間)のインスタンスに追加していき、そのあと各行を順に画面に表示する。
// fread4.cs
using System;
using System.IO;
using System.Text;
using System.Collections;
class FileRead4 {
static void Main() {
string line = "";
ArrayList al = new ArrayList();
using (StreamReader sr = new StreamReader(
"readme.txt", Encoding.GetEncoding("Shift_JIS"))) {
while ((line = sr.ReadLine()) != null) {
al.Add(line);
}
}
for (int i = 0; i < al.Count; i++) {
Console.WriteLine(al[i]);
}
}
}
// コンパイル方法:csc fread4.cs
' fread4.vb
Imports System
Imports System.IO
Imports System.Text
Imports System.Collections
Class FileRead4
Shared Sub Main()
Dim line As String = ""
Dim al As New ArrayList
Using sr As StreamReader = New StreamReader( _
"readme.txt", Encoding.GetEncoding("Shift_JIS"))
line = sr.ReadLine()
Do Until line Is Nothing
al.Add(line)
line = sr.ReadLine()
Loop
End Using
For i As Integer = 0 To al.Count - 1
Console.WriteLine(al.Item(i))
Next i
End Sub
End Class
' コンパイル方法:vbc fread4.vb
ArrayListクラスは可変長の配列として利用できる。テキストファイルは一度全体を読み込んでみなければ、全体の行数は分からない。このため、宣言時にその要素数を指定しなければならない通常の配列は、このような場合には適当ではないだろう。ArrayListクラスについては「TIPS:配列のサイズを変更するには?」で解説している。なお、読み込んだ各行には改行コードは含まれない。
.NET Framework 2.0以降では、ArrayListクラスに代えてList<T>ジェネリックコレクション(System.Collections.Generic名前空間)を使うとよい。string型のまま格納できるので、取り出す際にいちいちキャストする手間が不要になる。
なお.NET Framework 2.0では、ファイルを開き、内容を読み込み、閉じるという一連の処理を1つのメソッド呼び出しで可能とするReadAllTextメソッドとReadAllLinesメソッドがFileクラス(System.IO名前空間)に追加されている。これについては「TIPS:テキスト・ファイルの内容を簡単に読み込むには?」で解説している。
利用可能バージョン:.NET Framework 全バージョン
カテゴリ:クラスライブラリ 処理対象:テキストファイル
使用ライブラリ:StreamReaderクラス(System.IO名前空間)
使用ライブラリ:Encodingクラス(System.Text名前空間)
使用ライブラリ:ArrayListクラス(System.Collections名前空間)
関連TIPS:文字列をシフトJISとしてバイト列に変換するには?
関連TIPS:確実な終了処理を行うには?
関連TIPS:配列のサイズを変更するには?
関連TIPS:テキスト・ファイルの内容を簡単に読み込むには?[2.0のみ、C#、VB]
関連TIPS:テキスト・ファイルの内容を簡単かつ効率的に読み込むには?[4以降、C#、VB]
関連TIPS:テキストファイルの内容を非同期的に読み込むには?[C#/VB、.NET 4.5]
関連TIPS:ファイルにテキストを書き込むには?[C#、VB]
関連TIPS:バイナリ・ファイルを読み書きするには?
関連TIPS:テキストファイルの内容を非同期的に書き込むには?[C#/VB、.NET 4.5]
関連TIPS:バイナリファイルを非同期的に読み書きするには?[C#/VB、.NET 4.5]
【2018/07/11】Visual Studio 2017でコードの動作検証、図版の追加、全般的な構成の変更などを行いました。
【2008/08/14】VB(Visual Basic)のコード例とサンプルプログラムを追加しました。
【2003/06/13】初版公開。
Copyright© Digital Advantage Corp. All Rights Reserved.