一回も披露したことのない豆知識

プログラミング超初心者なのですが、
下記のような内容のファイルを読み書きするVB.NETのサンプルコードを知りたいです。
INIファイルと似たような内容ですが、セクション([Name])が無いのとコメント行が#です。

【やりたい事】
・「exampleAA = "before"」という行を「exampleAA = "after"」のように書き換えたいです。
・「#exampleBB = "before"」という行を「exampleBB = "before"」のようにコメント解除したいです。
・「abc0:0.defg = "hijk-lmn"」という行を「#abc0:0.defg = "hijk-lmn"」のようにコメントアウトしたいです。
・これらを変更してファイルに上書き保存したいです。

【ファイル内容】
#コメント行
exampleAA = "before"
#exampleBB = "before"
abc0:0.defg = "hijk-lmn"
以降、同じように行があります。

【内容詳細】
・コメント行は「#」で始まります。
・他の行は「KeyName = "Value"」といった形です。

【ファイル情報】
文字コード:Shift-JIS
改行コード:CR+LF

【環境】
 ・Visual Studio:Visual Studio 2019
 ・言語種類:Visual Basic
 ・プロジェクト:Windows フォーム アプリケーション(.NET Framework)
 ・フレームワーク:.NET Framework 4.7.2

よろしくお願いします。

質問者からの補足コメント

  • つらい・・・

    ありがとうございます。
    質問内容のコードそのものを教えていただけませんか?

    No.1の回答に寄せられた補足コメントです。 補足日時:2021/06/25 11:20
  • つらい・・・

    ありがとうございます。
    質問内容のコードそのものを教えていただけませんか?

    No.2の回答に寄せられた補足コメントです。 補足日時:2021/06/25 11:20
  • INI形式で解決との事ですが、セクション指定なしで読み書き可能なのでしょうか?

    補足の追加と変更です。

    【内容詳細】
    ・ファイルをINI形式に変更する事での解決は出来ません。(質問は手段ではなくて目的です)

    【ファイル情報】
    文字コード:UTF-8
    改行コード:CR+LF

    よろしくお願いします。

      補足日時:2021/06/25 11:30
  • つらい・・・

    度々ありがとうございます。
    お陰様で読み込みは出来たのですが、下記の4つを行うコードはどうすればいいのでしょうか?
    >【やりたい事】
    >・「exampleAA = "before"」という行を「exampleAA = "after"」のように書き換えたいです。
    >・「#exampleBB = "before"」という行を「exampleBB = "before"」のようにコメント解除したいです。
    >・「abc0:0.defg = "hijk-lmn"」という行を「#abc0:0.defg = "hijk-lmn"」のようにコメントアウトしたいです。
    >・これらを変更してファイルに上書き保存したいです。

    No.3の回答に寄せられた補足コメントです。 補足日時:2021/06/25 15:19

A 回答 (4件)

テキトーに作りました。


綺麗にするのはご自由にどうぞ。
動作保証についてはあなたの要件に対してしっかり行い、問題があるなら自力で直してください。

https://paiza.io/projects/5JGRdY4VknlCmjPfpeo2Cg

paiza.io上はコンパイルエラーになっていますが、コードを自分の環境に張り付ければ動きます。
    • good
    • 0
この回答へのお礼

助かりました

度々回答ありがとうございます。
早速、作っていただいた内容を試してみたいと思います。
またアドバイス通り、今後は少しでも自分で実現できるように頑張ってみます!

お礼日時:2021/06/28 18:20

ini形式にして、固定のセクションを1つ持てば解決しますよね。


ただし、ファイルエンコーディングはUTF-8 BOMありでは読み込めません。

固定セクションを1つすら持ちたくないなら、自前で実装するしかありません。
下記は、極力GetPrivateProfileString()に動作を合わせています。

超初心者かどうかはともかく、ヒントから情報を調べて構築して実現する力、実現できなかったとしてもどこまで考えられたのかを提示する質問能力などがないといけません。
また何かにハマると、親切な回答者から正しい回答が得られるとは限りませんよ。
回答が得られなくても、多少のことは自力で構築できる力がないと、回答が得られなかった時、自分のことなのに、あなたが困ろうがどうでもいい部類の他人任せになってしまいます。

Imports System.IO
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.Text.RegularExpressions

Module Module1

' iniファイル読込の場合に使うP/Invoke
Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (
<MarshalAs(UnmanagedType.LPStr)> ByVal lpApplicationName As String,
<MarshalAs(UnmanagedType.LPStr)> ByVal lpKeyName As String,
<MarshalAs(UnmanagedType.LPStr)> ByVal lpDefault As String,
<MarshalAs(UnmanagedType.LPStr)> ByVal lpReturnedString As StringBuilder,
ByVal nSize As UInt32,
<MarshalAs(UnmanagedType.LPStr)> ByVal lpFileName As String) As UInt32

Sub Main()
' iniファイルの読込 UTF-8 BOMありでは読めない
Dim result As New StringBuilder(100)
Dim directory As String = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
Dim intRet As Integer = GetPrivateProfileString("SECTION1", "KEY1",
"aaaa", result,
result.Capacity - 1, ".\test-ini.ini")
Console.WriteLine(result.ToString())


' iniファイルもどきの読込
Console.WriteLine(NearIni.GetString("KEY1", "", ".\test-nearini.ini"))

Console.ReadLine()
End Sub

End Module

''' <summary>
''' iniファイルもどき
''' </summary>
Module NearIni
Public Function GetString(key As String, defaultValue As String, fileName As String) As String
Dim regex As New Regex("^([^#][^\s]+)\s*=\s*(.+)", RegexOptions.Compiled)

Try
Using fs As FileStream = File.Open(fileName, FileMode.Open, FileAccess.Read),
sr As StreamReader = New StreamReader(fs, Encoding.UTF8)

Do While sr.Peek() > -1
Dim line As String = sr.ReadLine().Trim()

' 空行は無視
If (line.Trim() = String.Empty) Then
Continue Do
End If

Dim m As Match = regex.Match(line)

' パターンマッチしない行は無視
If m.Length = 0 Then
Continue Do
End If

' キーが合致しなければ無視
If m.Groups(1).Value <> key Then
Continue Do
End If

Return m.Groups(2).Value
Loop
Return defaultValue
End Using

Catch e As FileNotFoundException
Return defaultValue
End Try
End Function
End Module
この回答への補足あり
    • good
    • 0

それを求めている人はいないと思います。


なぜなら、ini形式を取れば解決するからです。

方法論は下記になります。
1.ファイルを1行ずつ読み込む。
2.正規表現 ^[^#](.+)\s*=\s*(.+) にマッチしたものを対象にする。
3.\1をtrimしたものをキー、\2をtrimしたものを値としたDictionaryを作る。

【対象】
aaa=aaa
aaa = aaa
aaa = aaa
aaa=aaa
#aaa=aaa
 #aaa=aaa

【対象外】
#aaa=aaa
#aaa = aaa
#aaa = aaa

#より前に何があるかによって制御が変わるなら、正規表現をもう少し考えるか、ごりごり判断するかします。


そうではなくて、常にそのファイルを読み込んで、対象キー情報を得る、という形を取るなら、
例えばaaaというキーの値を取りたいなら、
1.ファイルを1行ずつ読み込む。
2.正規表現 ^aaa\s*=\s*(.+) にマッチしたものを対象にする。
3.aaaがキー、\1をtrimしたものを値とする。

【対象】
aaa=aaa
aaa = aaa
aaa = aaa

【対象外】
aaa=aaa
#aaa=aaa
 #aaa=aaa
#aaa=aaa
#aaa = aaa
#aaa = aaa

実際に様々な値が入ってきた場合に要件に合致するように実装しなければなりません。
(値に=が入ってたらどうなるのか、など)
この回答への補足あり
    • good
    • 0

多分、良いサンプルは無いかと。

要求仕様が微妙に面倒なため、サンプルの域を超えるものを書かなきゃいけないので。

基本File.ReadLinesで1行ずつ読み込んで、#始まりならコメント、それと別にkey=Value形式ならそのpairの情報に分解する正規表現で字句解析する。それを保持する構造体のリストを構成する――みたいのをプログラムするとか。排他制御も考慮する必要があるかも。

それか素直にINI形式に則るとか。
https://docs.microsoft.com/en-us/dotnet/core/ext …
この回答への補足あり
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報