滅びゆくレガシーを、堅牢な自動化エンジンへと昇華させる――System.IOの真髄
VBAで構築された場当たり的なファイル操作に辟易している諸君へ。
「ファイルがロックされていて落ちた」「フォルダがなくて例外が発生した」。そんな現場の悲鳴を鎮めるのは、泥臭いエラーハンドリングの継ぎ足しではない。OSと.NETランタイムの対話の作法を、根底から理解することだ。
今日は、業務自動化の生命線である`System.IO`名前空間を用いた、極限まで堅牢なファイルI/Oの作法を伝授する。
—
1. 存在確認の「落とし穴」を回避せよ
初心者は`File.Exists`を呼んだ直後に`File.Open`を行う。これが大惨事の元だ。
マルチタスクなWindows環境では、`Exists`を実行した瞬間に別のプロセスがファイルを削除・移動する可能性がある(Time-of-check to time-of-use、通称TOCTOU問題)。
真のアーキテクトは「存在確認」ではなく「例外による制御」を優先する。 存在確認はあくまでログ出力やUIの分岐に留め、操作は「Try-Catch」で囲むのが鉄則だ。
Imports System.IO
Public Sub SafeFileRead(ByVal filePath As String)
‘ 存在確認はログ出力用。実操作はTry-Catchで囲み、OSからの拒絶に備える
If Not File.Exists(filePath) Then
Console.WriteLine(“Target file missing: ” & filePath)
Return
End If
Try
‘ ファイル共有モードを明示的に指定し、他プロセスの介入を許容または拒絶する
Using sr As New StreamReader(New FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
Dim content As String = sr.ReadToEnd()
‘ ここでビジネスロジックを展開
End Using
Catch ex As IOException
‘ ファイルロック等のOSレベルの例外を握りつぶさない
Logger.Error(“I/O Error: ” & ex.Message)
End Try
End Sub
2. メモリとハンドルの解放:IDisposableの絶対的な遵守
`StreamReader`や`FileStream`を「なんとなく」使っていないか?
VB.NETのガベージコレクション(GC)を過信してはならない。特に、大量のCSVをループ処理で読み込む際、`Using`ステートメントを省略することは、メモリリークとハンドル枯渇を招く死の行軍である。
`Using`ブロックは、例外発生時であっても確実に`Dispose()`を呼び出す。これは単なるシンタックスシュガーではなく、アンマネージドリソースをOSに即座に返還するための「契約」だ。
3. ディレクトリ操作:再帰の美学と防御的コーディング
フォルダ作成も同様だ。`Directory.CreateDirectory`は、対象が既に存在していても例外を吐かないという極めて優秀な設計になっている。これを自分で`If Not Exists`で囲むのは冗長である。
Public Sub EnsureDirectory(ByVal path As String)
‘ 既に存在すれば何もしない。存在しなければ親階層を含めて再帰的に作成する
‘ 戻り値のDirectoryInfoは、後続のパーミッション設定等に利用可能
Dim di As DirectoryInfo = Directory.CreateDirectory(path)
‘ レガシーシステム連携では、ディレクトリ作成後のアクセス権確認が必須
‘ 必要に応じてACL(Access Control List)の検証を組み込むこと
End Sub
4. レガシー連携の極意:Windows APIとの距離感
VB.NETでどうしても解消できない競合や、特殊な排他制御が必要な場合、`kernel32.dll`の`CreateFile`を直接叩く必要が出てくる。しかし、これは「最後の手段」だ。
- 極限の知見: .NETの`FileShare`列挙体で解決できるならば、決してWindows APIを呼び出してはならない。P/Invoke(プラットフォーム呼び出し)は、マネージド環境のメモリ安全性を棄損するリスクを孕んでいるからだ。
- パフォーマンス: 大量ファイル処理において、`File.ReadAllLines`はメモリを浪費する。行単位のストリーミング処理(`StreamReader.ReadLine`)こそが、数ギガバイトのログファイルを捌くための唯一の正解である。
結びに:コードは「対話」である
諸君が書くコードは、ただ動けばいいのではない。
OSという巨大なシステムに対し、どれだけ行儀よく振る舞い、どれだけ静かにリソースを解放できるか。その「礼儀」こそが、業務システムを数十年生き延びさせるエンジニアリングの真髄だ。
VBAの泥沼から脱出し、.NETの堅牢な世界へ踏み出したその一歩を、誇りを持って歩み続けよ。
技術は裏切らない。ただ、設計の甘さだけが、後で自分自身に牙を向くだけだ。
