特殊なINIファイルの読み取り方法

タグの編集
投稿者 heaven  (社会人) 投稿日時 2011/1/28 16:28:31
こんにちは。
現在あるアプリから吐き出されたINIのデータを取得しようとしているのですが、
一部のエントリーがこの様な形になっており取得の方法に困っています。

[Section1]
データ
データデータ
データデータデータ

[Section2]
データ
データデータ
データデータデータ

[Section3]
データ
データデータ
データデータデータ





上記のキー及び値のないセクション内のデータを取得したいのですが、INI関数(GetPrivateProfileString)などを使っても取得できなかったので、何か良い方法はありませんか?

投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/1/28 18:12:31
[Section1]
データ=

でも無いのですよね?

> INIのデータを取得しようとしているのですが
それは拡張子が ini なテキストファイルというだけであって、
Windows 標準の ini ファイルとは別物ですね。

> 取得の方法に困っています。
単純に上から一行ずつ読み取ってみては如何でしょう。

Imports System.IO
Imports System.Text.RegularExpressions
Imports System.Text

Public Class Form1

    Private mFilePath As String = "C:\test.ini"
    Private iniData As XDocument

    Private Sub Form1_Load(ByVal sender As ObjectByVal e As EventArgs) Handles MyBase.Load
        TextBox1.Text = "Section2"
        Button1.Text = "読み込み"
    End Sub

    Private Sub Button1_Click(ByVal sender As ObjectByVal e As EventArgs) Handles Button1.Click
        ListBox1.DataSource = ReadSection(mFilePath, TextBox1.Text)
    End Sub


    Private Function ReadSection(ByVal filePath As StringByVal sectionName As StringAs String()
        Dim rPattern As New Regex("^[[](?<X>.+)[]]$")

        Dim lst As New List(Of String)()
        Dim found As Boolean = False
        For Each row As String In File.ReadAllLines(filePath, Encoding.GetEncoding("Shift_JIS"))
            Dim m = rPattern.Match(row)
            If m.Success Then
                If found Then
                    Exit For
                ElseIf m.Groups("X").Value = sectionName Then
                    found = True
                End If
            ElseIf found Then
                lst.Add(row)
            End If
        Next
        Return lst.ToArray()
    End Function

End Class
投稿者 heaven  (社会人) 投稿日時 2011/1/28 20:17:01
魔界の仮面弁士さまご回答ありがとうございます。
はい、通常のINIに独自のデータを格納しているテキストファイルです。


> 単純に上から一行ずつ読み取ってみては如何でしょう。

私も同じ様な事を考えまして、INIをReadLineで一行ずつ読み取って指定したセクションをRegex.IsMatchで検索し、見つかれば次のセクションが見つかるまでデータを読み取るという形をやってみましたがどうも上手くいきませんでした・・(汗


魔界の仮面弁士さまのコードを試してみましたところセクション内のデータを取得することに成功しました。
本当にありがとうございます。



一つ気になったのですが、この変数は必要なのでしょうか?
Private iniData As XDocument
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/1/28 20:37:58
> 一つ気になったのですが、この変数は必要なのでしょうか?
> Private iniData As XDocument

あー。済みません。不要です。

VB2008 用の検証コードを作った時、提示したコードの前に
下記の XML 形式に変換するメソッドを作っていたので、その名残です。

iniData = <?xml version="1.0"?>
          <ini>
              <section name="Section1">
                  <data>データ</data>
                  <data>データデータ</data>
                  <data>データデータデータ</data>
              </section>
              <section name="Section2">
                  <data>データ</data>
                  <data>データデータ</data>
                  <data>データデータデータ</data>
              </section>
              <section name="Section3">
                  <data>データ</data>
                  <data>データデータ</data>
                  <data>データデータデータ</data>
              </section>
          </ini>



この形式にしておくと、

'XPath 式による問い合わせ 

'Imports System.Xml.XPath 
ListBox1.DataSource = iniData.XPathSelectElements("//section[@name='Section2']/data").ToList()

とか、

'Linq による問い合わせ 
Dim s() As String = (From q In iniData.Root.<section>.<data> _
                     Where q.Parent.@name = "Section3" _
                     Select q.Value).ToArray()


と書けて、後で取り出しやすくなるかな…と思って作ってみたのですが、
実際には Dictionary クラスで管理した方が使いやすかったです。