none
FileStreamからの読み込みで、末尾を判断する方法 RRS feed

  • 質問


  • 1レコードが20バイトから成る連続的なデーターを書き込んだファイルから、全てのレコードを読み出す処理をするサンプルプログラムです。
    レコード数は未知です。

        Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
            Dim byteArray(20) As Byte
            ' C:\DATA1.dat は任意のバイナリーファイルである
            Dim FileStream1 = New System.IO.FileStream("C:\DATA1.dat", System.IO.FileMode.Open, System.IO.FileAccess.Read)

            Do
                FileStream1.Read(byteArray, 0, byteArray.GetLength(0))
                Debug.Print(FileStream1.Position)
            Loop
     
        End Sub
    上のようなプログラムを書いたのですが、ファイルの末尾を判断する方法が分かりません。末尾に達しても例外が発生せず、無限ループになっているのが分かると思います。

    ファイルの末尾を判断する方法を教えて下さい。ネットで調べても、有効な回答が見つかりませんでした。
    2016年12月15日 2:47

回答

  • Positionが位置になるので、PositionがFileStreamのLength以上になったら最後まで読み切ったことになります。
    ですからループの判定をFileStream1.PositionとFileStream1.Lengthで比較すればよいことになります。

    あるいはRead関数の戻り値は読み取ったバイト数なので、それが読み取りたかったバイト数よりも少なかったら終端と判定することも可能です。

        Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs)
            Dim byteArray(18) As Byte '20バイト読み取るなら0から19までの20個
            ' C:\DATA1.dat は任意のバイナリーファイルである
            Dim FileStream1 = New System.IO.FileStream("C:\DATA1.dat", System.IO.FileMode.Open, System.IO.FileAccess.Read)
    
    
            'インデックス+19が20個目
            Do While (FileStream1.Position < FileStream1.Length)
                FileStream1.Read(byteArray, 0, byteArray.GetLength(0))
                Debug.Print(FileStream1.Position)
            Loop
    
            ''読み取ったバイト数が不足していたら終端としてもいいです
            'Do
            '    If (FileStream1.Read(byteArray, 0, byteArray.GetLength(0)) <> byteArray.GetLength(0)) Then
            '        Exit Do
            '    End If
            '    Debug.Print(FileStream1.Position)
            'Loop
    
        End Sub

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 編集済み gekkaMVP 2016年12月15日 3:46
    • 回答としてマーク huahi11112 2016年12月15日 7:10
    2016年12月15日 3:45

すべての返信

  • Positionが位置になるので、PositionがFileStreamのLength以上になったら最後まで読み切ったことになります。
    ですからループの判定をFileStream1.PositionとFileStream1.Lengthで比較すればよいことになります。

    あるいはRead関数の戻り値は読み取ったバイト数なので、それが読み取りたかったバイト数よりも少なかったら終端と判定することも可能です。

        Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs)
            Dim byteArray(18) As Byte '20バイト読み取るなら0から19までの20個
            ' C:\DATA1.dat は任意のバイナリーファイルである
            Dim FileStream1 = New System.IO.FileStream("C:\DATA1.dat", System.IO.FileMode.Open, System.IO.FileAccess.Read)
    
    
            'インデックス+19が20個目
            Do While (FileStream1.Position < FileStream1.Length)
                FileStream1.Read(byteArray, 0, byteArray.GetLength(0))
                Debug.Print(FileStream1.Position)
            Loop
    
            ''読み取ったバイト数が不足していたら終端としてもいいです
            'Do
            '    If (FileStream1.Read(byteArray, 0, byteArray.GetLength(0)) <> byteArray.GetLength(0)) Then
            '        Exit Do
            '    End If
            '    Debug.Print(FileStream1.Position)
            'Loop
    
        End Sub

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 編集済み gekkaMVP 2016年12月15日 3:46
    • 回答としてマーク huahi11112 2016年12月15日 7:10
    2016年12月15日 3:45
  • gekkaさん、ありがとうございました。返答が遅れまして済みません。
    FileStream1.Position : FileStream1.Length との比較で正常に動作しました。


    >あるいはRead関数の戻り値は読み取ったバイト数なので、それが読み取りたかったバイト数よりも少なかったら終端と判定することも可能です。 と回答いただきましたが、質問前に調べていたところ、MSDNのドキュメントに、下のような記述がありました。


    FileStream.Read メソッドの戻り値
    https://msdn.microsoft.com/ja-jp/library/system.io.filestream.read%28v=vs.110%29.aspx

    バッファーに読み取られた合計バイト数。 要求しただけのバイト数を読み取れなかった場合、この値は要求したバイト数より小さくなります。ストリームの末尾に到達した場合は 0 になることがあります。

    ↑ この、0になることがあります という記述なのですが、結果が不確定という意味にも取られるので、私としては怖くて使えませんでした。

    2016年12月15日 7:22
  • FileStream.Read メソッドの戻り値
    https://msdn.microsoft.com/ja-jp/library/system.io.filestream.read%28v=vs.110%29.aspx

    バッファーに読み取られた合計バイト数。 要求しただけのバイト数を読み取れなかった場合、この値は要求したバイト数より小さくなります。ストリームの末尾に到達した場合は 0 になることがあります。

    ↑ この、0になることがあります という記述なのですが、結果が不確定という意味にも取られるので、私としては怖くて使えませんでした。

    誤解を与えたのなら翻訳ミスでしょう。原文

    The total number of bytes read into the buffer. This might be less than the number of bytes requested if that number of bytes are not currently available, or zero if the end of the stream is reached.

    です。原文2文目を訳文では分割してしまっているために原文のmightが不正確な場所で訳されています。正確に訳すなら

    この戻り値は、もし要求しただけのバイト数を読み取れなかった場合は要求されたバイト数より小さく、またもしストリームの末尾に到達した場合は0に、それぞれなることがあります。

    ぐらいでしょうか。

    1文目「バッファーに読み取られた合計バイト数。 」を否定する記述ではなく、読み取られたバイト数が要求したバイト数と一致しない可能性について言及しているだけです。

    2016年12月15日 8:24