1

ランダム アクセス ファイルを読み込もうとしていますが、最初のファイルで次のエラーが発生しますError 5 (unable to read beyond end of the stream)。ここで何が間違っているのかわかりません。どうすればこの問題を解決できますか?

Structure StdSections
    'UPGRADE_WARNING: Fixed-length string size must fit in the buffer. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="3C1E4426-0B80-443E-B943-0627CD55D48B"'
    <VBFixedString(15), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=15)> Public A() As Char 'BEAM  --- complete beam designation          15
    'UPGRADE_WARNING: Fixed-length string size must fit in the buffer. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="3C1E4426-0B80-443E-B943-0627CD55D48B"'
    <VBFixedString(2), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=2)> Public B() As Char 'DSG   --- shape  ie "W" or "C"                2
    Dim C As Single 'DN    --- nominal depth of section            4
    Dim d As Single 'WGT   --- weight                              4
    .
    .
    .
End structure
''Note 'File1'is the existing RAF and holds complete path!

        Dim i,ffr,fLength,lastmembNo as integer
        sectionFound = False
        Dim std As new StdSections 
        fLength = Len(std)
        If fLength = 0 Then fLength = 168 ' 177
        ffr = FreeFile()
        FileOpen(ffr, File1, OpenMode.Random, OpenAccess.Read, OpenShare.LockRead, fLength)
        lastmembNo = CInt(LOF(ffr)) \ fLength

        For i = 1 To lastmembNo
            FileGet(ffr, std, i)
            >>Error 5 (unable to read beyond end of the stream) <<<                  
            If Trim(memberID) = Trim(std.A) Then
                    sectionFound = True
                end if
        next i
4

3 に答える 3

1

わあフリーファイル!それは過去からの爆発です!

私はVB.NETで古いOpenFileなどのファイルアクセス方法を実際に使用したことがないので、推測しているだけですが、.NETでは多くの変数タイプのサイズが変更されました。たとえば、整数は32ビット(4バイト)になりました。シングルはまだ4バイトですが、ブール値は違うと思います。

また、.NETの文字列はデフォルトでASCIIではなくUnicodeであるため、.NET文字列変数の1文字=1バイトに依存することはできません。実際、.NETは実際に実行前にPC上でプログラムを「コンパイル」するため、昔のようにメモリ内に構造を簡単にレイアウトすることはできません。

新しい「ストリーム」ベースのオブジェクトに切り替えたい場合は、次のコードを使用して開始できます。

    Dim strFilename As String = "C:\Junk\Junk.txt"
    Dim strTest As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    Call My.Computer.FileSystem.WriteAllText(strFilename, strTest, False)
    Dim byt(2) As Byte
    Using fs As New FileStream(strFilename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)
      fs.Seek(16, SeekOrigin.Begin)
      fs.Read(byt, 0, 3)
      Dim s As String = Chr(byt(0)) & Chr(byt(1)) & Chr(byt(2))
      MsgBox(s)
      fs.Seek(5, SeekOrigin.Begin)
      fs.Write(byt, 0, 3)
    End Using
    Dim strModded As String = My.Computer.FileSystem.ReadAllText(strFilename)
    MsgBox(strModded)

ただし、古いメソッドを保持していることを非難することはありません。新しいメソッドでは、クラスを定義してから、Byte()からクラスのプロパティに変換するカスタムルーチンを用意する必要があります。単にファイルからメモリにバイトをロードするよりも多くの作業が必要です。

于 2012-09-17T06:32:09.157 に答える
0

OK、次のように「.NET 方式」に切り替える必要があると思います。

Imports System.IO
Imports System.Xml

Public Class Form1

  Public Const gintRecLen_CONST As Integer = 177

  Class StdSections2
    Private mstrA As String
    Public Property A() As String
      Get
        Return mstrA
      End Get
      Set(ByVal value As String)
        If value.Length <> 15 Then
          Throw New Exception("Wrong size")
        End If
        mstrA = value
      End Set
    End Property

    Private mstrB As String
    Public Property B() As String
      Get
        Return mstrB
      End Get
      Set(ByVal value As String)
        If value.Length <> 2 Then
          Throw New Exception("Wrong size")
        End If
        mstrB = value
      End Set
    End Property

    Public C(39) As Single

    Public Shared Function FromBytes(byt() As Byte) As StdSections2
      Dim output As New StdSections2

      If byt.Length <> gintRecLen_CONST Then
        Throw New Exception("Wrong size")
      End If
      For i As Integer = 0 To 14
        output.mstrA &= Chr(byt(i))
      Next i
      For i As Integer = 15 To 16
        output.mstrB &= Chr(byt(i))
      Next i
      For i As Integer = 0 To 39
        Dim bytTemp(3) As Byte
        output.C(i) = BitConverter.ToSingle(byt, 17 + 4 * i)
      Next i
      Return output
    End Function
  End Class

  Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.


  End Sub


  Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Dim strFilename As String = "C:\Junk\Junk.txt"
    Dim strMemberID As String = "foo"
    Dim intRecCount As Integer = CInt(My.Computer.FileSystem.GetFileInfo(strFilename).Length) \ gintRecLen_CONST
    Dim blnSectionFound As Boolean = False
    Using fs As New FileStream(strFilename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
      For intRec As Integer = 0 To intRecCount - 1
        Dim intRecPos As Integer = gintRecLen_CONST * intRec
        fs.Seek(intRecPos, SeekOrigin.Begin)
        Dim byt(gintRecLen_CONST - 1) As Byte
        fs.Read(byt, 0, gintRecLen_CONST)
        Dim ss2 As StdSections2 = StdSections2.FromBytes(byt)
        'MsgBox(ss2.A & ":" & ss2.C(3)) 'debugging
        If strMemberID.Trim = ss2.A.Trim Then
          blnSectionFound = True
          Exit For
        End If
      Next intRec
    End Using
    MsgBox(blnSectionFound.ToString)

  End Sub
End Class

.NET 文字列と Singles の配列を使用する StdSections2 というクラスを定義します。どこでも 0 から始まる配列を使用します。新しい FileStream オブジェクトを使用してファイルをロードし、Seek() コマンドを使用して必要な位置を見つけます。次に、生のバイトをファイルからロードし、Chr() と BitConverter.ToSingle() を使用して生のバイトを文字列とシングルに変換します。

于 2012-09-21T03:54:24.067 に答える