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 中,许多变量类型的大小都发生了变化。例如,一个 Integer 现在是 32 位(4 个字节),我认为 Boolean 是不同的,尽管 Single 仍然是 4 个字节。

此外,.NET 中的字符串默认为 Unicode,而不是 ASCII,因此您不能依赖 .NET 字符串变量中的 1 个字符 = 1 个字节。事实上,.NET 实际上是在运行之前在 PC 上“JIT 编译”程序,所以你不能像过去那样在内存中轻松布局结构。

如果您想切换到新的基于“流”的对象,这里有一些代码可以帮助您入门:

    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

我们定义了一个名为 StdSections2 的类,它使用 .NET 字符串和一个 Singles 数组。我们到处使用基于 0 的数组。我们使用新的 FileStream 对象加载文件,并使用 Seek() 命令找到我们想要的位置。然后我们从文件中加载原始字节,并使用 Chr() 和 BitConverter.ToSingle() 将原始字节转换为字符串和单曲。

于 2012-09-21T03:54:24.067 回答
0

我不确定您的示例,但是这个示例有效:

Public Class Form1

Const maxLenName = 30

Structure person
    <VBFixedString(maxLenName)> Dim name As String
    Dim age As Byte
End Structure

Private Sub Form1_Load(sender As [Object], e As EventArgs) Handles MyBase.Load

    Dim entryIn As New person
    Dim recordLen As Integer = Len(entryIn)
    Dim entry As person

    If FileIO.FileSystem.FileExists("test.raf") Then Kill("test.raf")
    FileOpen(1, "test.raf", OpenMode.Random,,, recordLen)

    'write
    entry.name = LSet("Bill", maxLenName)
    entry.age = 25
    FilePut(1, entry, 6) 'write to 6th record

    'read
    Dim nRecords As Integer = LOF(1) \ recordLen
    FileGet(1, entryIn, nRecords)
    FileClose(1)

    Dim personName As String = RTrim(entryIn.name)
    Dim personAge As Byte = entryIn.age

    MsgBox(personName & "'s age is " & personAge)
End Sub
End Class
于 2016-04-04T10:34:04.097 回答