none
大サイズファイル内容に対してメモリに展開せずに演算(ハッシュ値計算、OutOfMemoryException対策) RRS feed

  • 質問

  • 仕事で、ファイル整理するための情報を集めるプログラムを組んでいます。
    ファイルパスのString型を渡すとハッシュ値がString型で帰ってくる関数で
    解決しようとしたのですが、現在の私の開発環境では500MByteくらいの
    ファイルサイズを越えるとファイル内容のメモリへの読みこみの時点
    #My.Computer.FileSystem.ReadAllBytes(file)
    でOutOfMemoryExceptionでエラーになってしまいます。


        Private Function GetSHA256(ByVal file As String) As String
                Dim data As Byte()
                Try
                    data = My.Computer.FileSystem.ReadAllBytes(file)
                Catch ex As OutOfMemoryException
                    Return "<HASH_OUTOFMEMORY_FAILED>"
                    Exit Function
                End Try
                Dim result() As Byte
                Dim shaM As New SHA256Managed()
                result = shaM.ComputeHash(data)
                Return BitConverter.ToString(result).Replace("-", "")
        End Function


    VB2005、Framework2.0の標準的な機能で実装しようとした
    (SHA256Managed)為にいったん全ファイル内容をバイト列に
    取り込まないといけなくなっているのが問題なのは分かります。
    自力で考えると以下の解決策が浮かぶのですが、どの手が良いのか、
    また具体的な実装の書き方が分からず悩んでおります。
    どなたかアドバイスをいただけないでしょうか。

     解決策1)
     実は、ReadAllBytesをやめてstreamで一定サイズずつ読み込みながら
     SHA256Mnaged を用いて演算していく方法がある?
     
     解決策2)前述のstream化をした上で、SHA256Managedを捨てて
     SHA256計算部分を自力で書く
     
     解決策3)商用利用可能なDLLがあってそれを用いる(フリーでも可)

    最悪、SHA256のサンプルコードを探して自力で実装を試みるしかないでしょうか・・・
    実装できた当初は、標準機能で簡単に実装できたなあと喜んでおりました。
    2006年11月23日 13:43

回答

すべての返信

  • ComputeHashに思い切りStreamを受け取るものがあるんですが…

     

    2006年11月23日 14:25
  • ほ、ホントですね(汗
    ありがとうございます。
    こうしました。

         Private Function GetSHA256(ByVal file As String) As String

                Dim fs As FileStream = Nothing
                Try
                    fs = New FileStream(file, FileMode.Open)
                    Dim result() As Byte
                    Dim shaM As New SHA256Managed()
                    result = shaM.ComputeHash(fs)
                    Return BitConverter.ToString(result).Replace("-", "")
                Catch ex As OutOfMemoryException
                    Return HASH_OUTOFMEMORY_FAILED
                    ' 念のため
                Finally
                    fs.Close()
                End Try

      Exit Function



    今テストを始めました。
    1GByte程度のファイルに対して1ファイルあたり2分くらい。

    Intel(R) Pentium(R) 4 CPU 3.40GHz
    3393 MHz
    (GenuineIntel Family F Model 3 Stepping 4)
    L2 Cache=512 KB
    CPU の数    2
    物理メモリ (空き/総容量):    426 MB/0.99 GB (41%)
    仮想メモリ (空き/総容量):    1.96 GB/1.99 GB (98%)
    ページファイル (空き/総容量):    1.52 GB/2.40 GB (63%)

    の環境で片方のCPUががんばってます。でも50%~70%を行ったり来たり。
    更に速くする方法があるのだろうか・・・HDDもカリカリ言ってませんし、
    CPUのファンの音が少し大きくなったくらいで特別PCに負担は
    掛けていなさそうです。
    ちなみにBackGroundWorkerで裏で走らせてます。だからかしら?


    2006年11月23日 15:30