VB のたまご

作成日: 2015/12/03, 更新日: 2015/12/03


IOException について

概要

  •  IOException は、I/O エラーが発生した場合に発生する例外エラーですが、主には、ファイル読み込み時にアクセス拒否されて発生することが多いみたいです。 この場合、前処理で開いたまま閉じないで再度開こうとした、別のプログラムが開いているためこちらのプログラムでは開けない、ということが考えられます。


スポンサーリンク


事例と対処方法

  •  以下のサンプルは、意図的に例外エラーを発生させるコードです。 実際の業務プログラムでは、このような簡単なコードではないと思いますが、例外発生させている、直接的な原因となる部分として参考になるはずです。 また、本例外エラーが発生してしまう原因となった、根本的な原因となる別の例外エラーが、さらに奥深くにいる場合があります。 (本例外エラーは間接的に影響を受けて発生してしまったもので、本当の原因となる例外エラーを食い止めることで、本例外エラーも直る場合があります。)

  •  このような組み合わせのパターンは、本例外エラーに限らず、他の例外エラー全般にも言えることですが、そんなに頻繁に出くわすものではないと思いますので、 そういう場合もあるということだけ、覚えておいていただけると解決しやすくなるのではと思います。

  •  また、記載の対処方法は、あくまでも一例です。 他の対処方法の方が、その業務プログラムにとってベストプラクティスとなる場合もありますので、検討材料の1つという程度に確認していただければと思います。

  • スポンサーリンク



  • FileStream
  • ' 最初にログファイルを開いたままにしておく
    Dim logFile As String = "C:\Temp\myapp.log"
    Dim fs1 As New FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.None)
    Dim bs1(CInt(fs1.Length - 1)) As Byte
    fs1.Read(bs1, 0, bs1.Length)
    
    ' 別のプログラムでファイルを開こうとする
    Dim fs2 As New FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.None)
    Dim bs2(CInt(fs2.Length - 1)) As Byte
    fs2.Read(bs2, 0, bs2.Length)
    
    ' 例外エラー
    System.IO.IOException: 別のプロセスで使用されているため、プロセスはファイル 'C:\Temp\myapp.log' にアクセスできません。
       場所 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       場所 System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
       場所 System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
    
    ' 対処方法
    無し
    
  •  FileStream クラスを使うと、アクセスレベルや共有レベルを詳細に設定しながら、読み書きすることができます。 しかし、サンプルのように、第三引数の共有レベルを None(ファイルを閉じるまで読み書きを禁止する)にしてしまうと、他のプログラムから読み込めなくなってしまいます。 ファイルの読み書きは早い者勝ちなので、最初にこのようなプログラムが実行してしまうと、後から読み込もうとしたプログラム側で読み込みができなくなってしまいます。 ファイルを読み込もうとした際に、どのプログラムか分からないがファイルを読み込めない、または、どのプログラムか分かっているが、第三者が作成したプログラムの場合、 こちらのプログラムとしては、対策のしようがありません(私の調査不足であることを願います)。
  •  ここでは、こちらのプログラム側の問題だった場合についてだけ、対処方法を記載します。

  • ' 対処方法1
    読み取り命令の変更
    Dim logData As String = File.ReadAllText(logFile)
    
  •  安全で簡易的に扱える命令に変えてしまうという対処方法です。 File クラスの、Read~や Write~は、開閉処理を自動的に行ってくれるので、実装者は意識する必要が無くなります。

  • ' 対処方法2
    Using キーワードの使用
    Using fs1 As New FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.None)
        Dim bs1(CInt(fs1.Length - 1)) As Byte
        fs1.Read(bs1, 0, bs1.Length)
    End Using
    または、Close メソッドを必ず呼び出す
    
  •  使い終わったら必ず閉じる、という対処方法です(よく考えたら対処ではないですね)。 仕様によっては、他のプログラムからも読み込まれる可能性があることを考慮する必要があります。

  • ' 対処方法3
    該当ファイルを、自プログラムの場所にコピーして読み込む
    Imports System.IO
    
    Dim copiedFile As String = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "myapp.log")
    File.Copy(logFile, copiedFile)
    
  •  仕様変更になってしまうのと、ひと手間かかることになりますが、自分の場所にコピーして作業するという対処方法です。

  •  最後までこの記事を読んでいただき、ありがとうございました。

  • スポンサーリンク