ファイル操作 TextFieldParser オブジェクト ストリームの読込と書込 Microsoft.VisualBasic.FileIO 名前空間の TextFieldParser オブジェクトは 構造化テキストファイルの解析に使用するメソッドとプロパティを備えたオブジェクトで有る テキストファイルを TextFieldParser で解析するのは テキストファイルを反復処理するのと同じで有り ReadFields メソッドでテキストのフィールドを抽出するのは 文字列を分割するのと同じで有る TextFieldParser では デリミタ ( 区切記号 ) で区切られたファイルと固定幅のファイルの 2 種類のファイルを解析する事が出来る Delimiters プロパティや HasFieldsEnclosedInQuotes プロパティ等の一部のプロパティは デリミタで区切られたファイルで而巳有効で有り FieldWidths プロパティは 固定幅のファイルで而巳有効で有る TextFieldParser クラスの新しいインスタンスを生成するコンストラクタには 下記の 8 種類のオーバーロードが有る オーバーロード TextFieldParser(path) TextFieldParser(path, defaultencoding) TextFieldParser(path, defaultencoding, detectencoding) TextFieldParser(stream) TextFieldParser(stream, defaultencoding) TextFieldParser(stream, defaultencoding, detectencoding) TextFieldParser(stream, defaultencoding, detectencoding, leaveopen) TextFieldParser(reader) コンストラクタの引数は 下記の通りで有る 引数 型 解説 path String 解析されるファイルの絶対パス defaultencoding Encoding エンコーディングをファイルから特定出来ない場合に使用される文字エンコーディング ( 既定値は UTF8) detectencoding Boolean ファイルの先頭でバイト順マークを探すか何うかを指定 ( 既定値は True) stream Stream 解析されるストリーム leaveopen Boolean TextFieldParser オブジェクトを閉じる時に stream を開いた儘にするか何うかを指定 ( 既定値は False) reader TextReader 解析される TextReader ストリーム defaultencoding パラメータが指定されて居る場合 其れが 既定のエンコーディングと仕て使用される 亦 detectencoding パラメータが True の場合 ファイルやストリームの最初の 3 バイトを調べてエンコーディングを検出する ファイルが適切なバイト順マークで始まって居る場合は UTF-8 リトルエンディアン Unicode ビッグエンディアン Unicode の各テキストが自動的に認識されるが 其れ以外の場合は defaultencoding で指定されたエンコーディングが使用される 特定のカルチャ設定で文字セットをコンパイルし 同じ文字を別のカルチャ設定で取得する場合 文字を解釈出来ずに 例外がスローされる可能性が有る -1-
TextFieldParser オブジェクトのプロパティは 下記の通りで有る プロパティ 型 解説 CommentTokens String パーサーは指定されたコメントトークンで始まる行をスキップする Delimiters String テキストファイルの区切記号を指定する ( 区切記号入りファイルに対して而巳有効 ) EndOfData Boolean 現在のカーソル位置とファイルの末尾との間に空白行とコメント行しかない場合に True を返す ErrorLine String 直前に MalformedLineException を発生させた行を返す ( 既定値は "" ) ErrorLineNumber Long 直前に MalformedLineException を発生させた行番号を返す ( 既定値は-1) FieldWidths Integer テキストファイルの各列の幅を表す ( 固定幅のファイルに対して而巳有効 ) HasFieldsEnclosedInQuotes Boolean フィールドを二重引用符で囲む事が出来る場合に True を返す ( 区切記号入りファイルに対して而巳有効で 既定値は True) LineNumber Integer 現在の行番号を返すか 解析可能な文字が無く成った場合には -1 を返す TextFieldType FieldType 区切記号入りか固定幅のファイルの種類を表す ( 既定値は Delimited) TrimWhiteSpace Boolean フィールド値の前後の空白を切り取るか何うかを指定する TextFieldParser オブジェクトのメソッドは 下記の通りで有る メソッド Close PeekChars ReadFields ReadLine ReadToEnd SetDelimiters SetFieldWidths 解説基に成るストリームを閉じる 指定された数の文字を カーソルを進めずに読み取る 現在の行に有る総てのフィールドを読み込み 其れを文字列の配列と仕て返して カーソルを次の行に進める 現在の行を String 型で返し カーソルを次の行に進める ストリームの残りを読み取り 其れを String 型で返す リーダーの区切記号に指定された値を設定し フィールドの種類に Delimited を設定する リーダーの区切記号に指定された値を設定し field type に FixedWidth を設定する TextFieldParser オブジェクトを使用すると ログファイルやレガシデータベース情報等 区切文字や幅に応じて複数列に区切られたテキストから成る巨大なファイルの解析や処理が出来る テキストファイルを TextFieldParser で解析するのは テキストファイルを反復処理するのと同じで有り 解析メソッドでテキストのフィールドを抽出するのは 区切文字の付いた文字列を文字列操作メソッドでトークン化するのと同じで有る 様々な種類のテキストファイルの解析 テキストファイルは コンマやタブ等の文字で可変幅のフィールドに区切られて居る場合が有る 下記の例の様に TextFieldType と区切記号を定義する 下記の例では SetDelimiters メソッドを使用して タブ区切りのテキストファイルを定義して居る (Tr は TextFieldParser のインスタンス ) -2-
Tr.SetDelimiters(vbTab) Tr.SetDelimiters(vbTab); Visual Basic C# C# で使用する場合は Microsoft.VisualBasic の参照を追加する必要が有る 亦 テキストファイルに依っては 固定幅のフィールドを持つ場合も有る 其の場合には 下記の例の様に TextFieldType を FixedWidth と定義し 各フィールドの幅を定義する必要が有る 下記の例では SetFieldWidths メソッドを使用して テキストの列を定義して居る 最初は幅が 5 文字 其の次は 10 文字 其の次は 11 文字 其の次は可変幅で有る Tr.SetFieldWidths(5, 10, 11, -1) Tr.SetFieldWidths(5, 10, 11, -1); Visual Basic C# 書式を定義すれば ファイルをループし ReadFields メソッドを使用して 各行を順番に処理する フィールドが指定の書式に一致しない場合には MalformedLineException 例外がスローされる 此の例外がスローされた時には ErrorLine プロパティと ErrorLineNumber プロパティに 例外の原因に成ったテキストと 其のテキストの行番号が格納される コンマ区切りのテキストファイルの読込 TextFieldParser オブジェクトを使用すると ログ等の構造化されたテキストファイルを簡単に効率良く解析する事が出来る 区切記号が使用されたファイルと固定幅のテキストフィールドを持つファイルの孰れで有るかは TextFieldType プロパティで定義する Imports Microsoft.VisualBasic.FileIO Visual Basic Public Class TextFieldParseTest ' ボタン ( カンマ区切 ) がクリックされた時の処理 Private Sub btncomma_click(byval sender As System.Object, ByVal e As System.EventArgs) _ Handles btncomma.click ' ファイル名の設定 Dim F As String = Application.StartupPath If Not F.EndsWith(" ") Then F &= " " F &= "test.csv" ' TextFieldParser のインスタンス生成 Using Tr As TextFieldParser = New TextFieldParser(F, System.Text.Encoding.Default) ' TextField の型と区切記号を定義 Tr.TextFieldType = FieldType.Delimited Tr.SetDelimiters(",") ' カンマ区切 ( タブ区切の場合は Tr.SetDelimiters(vbTab)) ' 各行のループ -3-
Dim S( ) As String dgvdisp.rows.clear( ) Do Until Tr.EndOfData Try S = Tr.ReadFields( ) Dim R As DataGridViewRow = New DataGridViewRow( ) R.CreateCells(dgvDisp) For I As Integer = 0 To (S.Length - 1) R.Cells(I).Value = S(I) Next dgvdisp.rows.add(r) Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException MessageBox.Show(ex.LineNumber.ToString( ) & " 行目の書式が異常です!") Catch ex As Exception MessageBox.Show(" 予期せぬ例外が発生!") End Try Loop Tr.Close( ) End Using End Sub End Class C# // Microsoft.VisualBasic の参照を追加する事 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using Microsoft.VisualBasic.FileIO; namespace TextFieldParseTest public partial class TextFieldParseTest : Form public TextFieldParseTest( ) InitializeComponent( ); // ボタン ( カンマ区切 ) がクリックされた時の処理 private void btncomma_click(object sender, EventArgs e) -4-
// ファイル名の設定 string f = Application.StartupPath; if(! f.endswith(@" ")) f += @" "; f += "test.csv"; // TextFieldParser のインスタンス生成 using (TextFieldParser tr = new TextFieldParser(f, System.Text.Encoding.Default)) // TextField の型と区切記号を定義 tr.textfieldtype = FieldType.Delimited; tr.setdelimiters(","); // カンマ区切 ( タブ区切の場合は Tr.SetDelimiters(" t")) // 各行のループ string[] s; dgvdisp.rows.clear( ); while (!tr.endofdata) try s = tr.readfields( ); DataGridViewRow r = new DataGridViewRow( ); r.createcells(dgvdisp); for (int i = 0; i < s.length; i++) r.cells[i].value = s[i]; dgvdisp.rows.add(r); catch (Microsoft.VisualBasic.FileIO.MalformedLineException ex) MessageBox.Show(ex.LineNumber.ToString( ) + " 行目の書式が異常です!"); catch (Exception ex) MessageBox.Show(" 予期せぬ例外が発生! n" + ex.message); 固定幅のテキストファイルの読込 TextFieldParser オブジェクトを使用すると ログ等の構造化されたテキストファイルを簡単に効率良く解析する事が出来る 区切記号が使用されたファイルと固定幅のテキストフィールドを持つファイルの孰れで有るかは TextFieldType プロパティで定義する 固定幅のファイル内で 可変幅のフィールドを指定するには フィールド幅を -1 と仕て定義する -5-
Imports Microsoft.VisualBasic.FileIO Visual Basic Public Class TextFieldParseTest ' ボタン ( 固定長 ) がクリックされた時の処理 Private Sub btnfixed_click(byval sender As System.Object, ByVal e As System.EventArgs) _ Handles btnfixed.click ' ファイル名の設定 Dim F As String = Application.StartupPath If Not F.EndsWith(" ") Then F &= " " F &= "test.fix" ' TextFieldParser のインスタンス生成 Using Tr As TextFieldParser = New TextFieldParser(F, System.Text.Encoding.Default) ' TextField の型とフィールド幅を定義 Tr.TextFieldType = FieldType.FixedWidth Tr.SetFieldWidths(3, 4, -1) ' 3 文字 4 文字 可変長 ' 各行のループ Dim S( ) As String dgvdisp.rows.clear( ) Do Until Tr.EndOfData Try S = Tr.ReadFields( ) Dim R As DataGridViewRow = New DataGridViewRow( ) R.CreateCells(dgvDisp) For I As Integer = 0 To (S.Length - 1) R.Cells(I).Value = S(I) Next dgvdisp.rows.add(r) Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException MessageBox.Show(ex.LineNumber.ToString( ) & " 行目の書式が異常です!") Catch ex As Exception MessageBox.Show(" 予期せぬ例外が発生!") End Try Loop Tr.Close( ) End Using End Sub End Class C# // Microsoft.VisualBasic の参照を追加する事 using System; -6-
using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using Microsoft.VisualBasic.FileIO; namespace TextFieldParseTest public partial class TextFieldParseTest : Form public TextFieldParseTest( ) InitializeComponent( ); // ボタン ( 固定長 ) がクリックされた時の処理 private void btnfixed_click(object sender, EventArgs e) // ファイル名の設定 string f = Application.StartupPath; if (!f.endswith(@" ")) f += @" "; f += "test.fix"; // TextFieldParser のインスタンス生成 using (TextFieldParser tr = new TextFieldParser(f, System.Text.Encoding.Default)) // TextField の型とフィールド幅を定義 tr.textfieldtype = FieldType.FixedWidth; tr.setfieldwidths(5, 5, -1); // 5 文字 5 文字 可変長 // 各行のループ string[] s; dgvdisp.rows.clear( ); while (!tr.endofdata) try s = tr.readfields( ); DataGridViewRow r = new DataGridViewRow( ); r.createcells(dgvdisp); for (int i = 0; i < s.length; i++) r.cells[i].value = s[i]; dgvdisp.rows.add(r); catch (Microsoft.VisualBasic.FileIO.MalformedLineException ex) -7-
MessageBox.Show(ex.LineNumber.ToString( ) + " 行目の書式が異常です!"); catch (Exception ex) MessageBox.Show(" 予期せぬ例外が発生! n" + ex.message); フィールド幅の指定は 文字数で有り 全角と半角を問わず 1 文字と数える 複数の書式を持つファイルの解析 TextFieldParser オブジェクトの PeekChars メソッドを使用すると 各フィールドを読み込む前に書式の検証を行う事が出来る 此れに依り フィールドに対して複数の書式を定義して 適切に対応する事も出来る TextFieldParser オブジェクトを使用すると ログ等の構造化されたテキストファイルを簡単に効率良く解析する事が出来る PeekChars メソッドを使用して ファイルを解析する時に 各行の書式を判断する事に依り 複数の書式を持つファイルを処理する事が出来る 下記のコード例では 通常 3 項目 (5 文字 5 文字 可変長 ) のデータで 少数の 2 項目 (5 文字 可変長 ) のデータ ( 行頭に * が付いて居る ) が含まれる場合を処理して居る Imports Microsoft.VisualBasic.FileIO Visual Basic Public Class TextFieldParseTest ' ボタン ( 複合書式 ) がクリックされた時の処理 Private Sub btnmulti_click(byval sender As System.Object, ByVal e As System.EventArgs) _ Handles btnmulti.click ' ファイル名の設定 Dim F As String = Application.StartupPath If Not F.EndsWith(" ") Then F &= " " F &= "test.mix" ' 標準の書式と例外時の書式の定義 Dim StdFrm( ) As Integer = 5, 5, -1 Dim ErrFrm( ) As Integer = 5, -1 ' TextFieldParser のインスタンス生成 Using Tr As TextFieldParser = New TextFieldParser(F, System.Text.Encoding.Default) ' TextField の型とフィールド幅を定義 -8-
Tr.TextFieldType = FieldType.FixedWidth Tr.FieldWidths = StdFrm ' 各行のループ Dim S( ), C As String dgvdisp.rows.clear( ) Do Until Tr.EndOfData Try C = Tr.PeekChars(1) If C = "*" Then Tr.SetFieldWidths(ErrFrm) S = Tr.ReadFields() Tr.SetFieldWidths(StdFrm) Else S = Tr.ReadFields( ) End If Dim R As DataGridViewRow = New DataGridViewRow( ) R.CreateCells(dgvDisp) For I As Integer = 0 To (S.Length - 1) R.Cells(I).Value = S(I) Next dgvdisp.rows.add(r) Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException MessageBox.Show(ex.LineNumber.ToString() & " 行目の書式が異常です!") Catch ex As Exception MessageBox.Show(" 予期せぬ例外が発生!") End Try Loop Tr.Close( ) End Using End Sub End Class C# // Microsoft.VisualBasic の参照を追加する事 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using Microsoft.VisualBasic.FileIO; namespace TextFieldParseTest -9-
public partial class TextFieldParseTest : Form public TextFieldParseTest( ) InitializeComponent( ); // ボタン ( 複合書式 ) がクリックされた時の処理 private void btnmulti_click(object sender, EventArgs e) // ファイル名の設定 string f = Application.StartupPath; if (!f.endswith(@" ")) f += @" "; f += "test.mix"; // 標準の書式と例外時の書式の定義 int[] StdFrm = 5, 5, -1 ; int[] ErrFrm = 5, -1 ; // TextFieldParser のインスタンス生成 using (TextFieldParser tr = new TextFieldParser(f, System.Text.Encoding.Default)) // TextField の型とフィールド幅を定義 tr.textfieldtype = FieldType.FixedWidth; tr.fieldwidths = StdFrm; // 各行のループ string[] s; string c; dgvdisp.rows.clear( ); while (!tr.endofdata) try c = tr.peekchars(1); if (c == "*") tr.setfieldwidths(errfrm); s = tr.readfields( ); tr.setfieldwidths(stdfrm); else s = tr.readfields( ); DataGridViewRow r = new DataGridViewRow( ); r.createcells(dgvdisp); for (int i = 0; i < s.length; i++) -10-
r.cells[i].value = s[i]; dgvdisp.rows.add(r); catch (Microsoft.VisualBasic.FileIO.MalformedLineException ex) MessageBox.Show(ex.LineNumber.ToString( ) + " 行目の書式が異常です!"); catch (Exception ex) MessageBox.Show(" 予期せぬ例外が発生! n" + ex.message); -11-