【実務・中級編】初心者向け:VB.NETのConsoleアプリケーションにおける標準入出力制御:StreamReaderとStreamWriterでログを確実に書き出す基本 – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

現場のエンジニアへ:コンソールアプリの「標準入出力」を甘く見てはいけない理由

業務自動化ツールをVB.NETで書く際、初心者が陥りがちな罠がある。それは「コンソール出力(`Console.WriteLine`)で安心し、入力(`Console.ReadLine`)を無防備に受け取る」ことだ。

なぜこれが危険なのか。バッチ処理や自動化ツールにおいて、標準入出力は単なる「画面表示」ではない。それは「プロセスのインターフェース」であり、OSや後続のパイプラインと対話するための最前線だからだ。

本稿では、プロの現場で「止まらない、壊れない」ツールを作るために必須となる、`StreamReader`/`StreamWriter`を用いた堅牢な入出力制御の作法を伝授する。

1. なぜ「標準入出力」を制御すべきなのか

初心者が書くコードは、往々にして「例外が起きたら画面が消えて終わり」という脆弱なものだ。業務ツールであれば、以下の要件は最低限満たす必要がある。

  • ログの永続化: 画面に出た情報は消える。ファイルに吐き出せ。
  • リソースの即時解放: `Stream`はOSの資源を食う。使い終わったら即座に閉じる(Dispose)。
  • 例外耐性: 入力データが不正でも、ツール自体が異常終了してはならない。

これらを実現するのが、`.NET`のストリーム操作の基本である。

2. 堅牢なロギングを実現する「StreamWriter」の実装

ログを残す際、`File.AppendAllText` を多用していないか? 短い文字列なら良いが、高頻度で書き込む場合、毎回ファイルを開閉するオーバーヘッドは無視できない。

真のエンジニアは、「適切なタイミングでフラッシュし、最後に確実に閉じる」

Imports System.IO

Public Sub WriteLog(message As String)
‘ ログファイルのパス(絶対パスで指定するのが鉄則)
Dim logPath As String = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, “app_log.txt”)

‘ Usingブロックを使う。これがVB.NETの「鉄の掟」だ。
‘ StreamWriterは内部的にバッファを持つため、Close/Disposeを忘れるとログがファイルに書き込まれない。
Using sw As New StreamWriter(logPath, append:=True)
sw.WriteLine($”{DateTime.Now:yyyy/MM/dd HH:mm:ss} – {message}”)
‘ AutoFlushをTrueにするか、明示的にFlushを呼ぶことで、
‘ アプリがクラッシュした際にも直前までのログを保護できる
sw.Flush()
End Using
End Sub

ポイント: `Using` ブロックは、処理終了時に自動的に `Dispose` を呼び出す。例外が発生しても確実にリソースを解放する、最も安全な設計パターンだ。

3. 安全な入出力制御:コンソール入力の「作法」

ユーザー入力は「常に予期せぬもの」と考えるのがセキュリティの基本だ。`Console.ReadLine()` で受け取った文字列をそのまま使うのは自殺行為に近い。

以下のコードは、入力のバリデーション(妥当性検証)を組み込んだ実用的な雛形である。

Public Sub RunInputProcess()
Console.WriteLine(“処理IDを入力してください:”)

‘ 入力は常にNothing(null)の可能性があることを忘れるな
Dim input As String = Console.ReadLine()

‘ 入力チェック:空文字や不要な空白を除去して判定する
If String.IsNullOrWhiteSpace(input) Then
WriteLog(“エラー: 入力が空です。”)
Return
End If

Try
‘ ここで業務ロジックを実行する
‘ 例: ProcessData(input.Trim())
WriteLog($”処理を開始: ID={input.Trim()}”)
Catch ex As Exception
‘ 予期せぬエラーは必ずログへ
WriteLog($”致命的なエラー発生: {ex.Message}”)
End Try
End Sub

4. プロダクション環境での「3つの戒律」

現場で生き残るツールを作るために、以下の3点は心に刻んでおいてほしい。

1. 絶対パスを使用せよ: カレントディレクトリは、バッチを起動する場所によって変動する。`AppDomain.CurrentDomain.BaseDirectory` を起点にパスを組み立てること。
2. エンコーディングを明示せよ: デフォルトの文字コードに依存すると、Windows/Linux混在環境や旧来の文字コードで文字化けを引き起こす。UTF-8(BOMなし)が現代の標準だ。

  • `New StreamWriter(path, True, System.Text.Encoding.UTF8)`

3. 例外を握りつぶすな: `Catch` でログを出力したら、必要な場合は `Throw` で呼び出し元に伝えるか、プログラムを終了させる判断をせよ。

最後に:コードは「対話」である

自動化ツールは、無言で動いて終わるものではない。それは、次にメンテナンスする「未来の自分」や、それを使う「現場の担当者」との対話だ。

`StreamReader`/`StreamWriter` を正しく使い、ログという「足跡」を残す設計を徹底してほしい。そうすれば、あなたの書いたコードは、バグの温床ではなく、業務を支える堅牢なインフラへと進化するはずだ。

次は、このログをデータベースへ直接流し込む非同期処理の設計について話そう。準備はいいか?

タイトルとURLをコピーしました