Reading a binary file with VB.NET

Posted on 2006-05-31
Last Modified: 2012-05-05
Let's try this again, a little more concisely:

I am trying to convert some code from VB6.0 to VB.NET, this particular loop populates a data structure from a binary file, and I am having a huge problem getting equivalent results.  I'll cut and paste the old code and new code below, and if anyone can tell me what I'm doing wrong, or (even better!) give me a couple of snippets, I'd be eternally graceful!  

The problems are in the GetVariable function of the second section.  Just pasted the rest for completeness.  Part of the problem this isn't simple is because the BinaryReader doesn't seem to support random access... but I'm not married to it.


old, working VB6.0 code

Private Type XVDataType

    sText As String * 50
    iNumPoints As Integer
    dData(50) As Double

End Type

Private Sub ButtonGo_Click()
     Dim X as XVDataType

     Dim f as String
     f = "C:\Documents and Settings\crice\My Documents\Active Tasks\TCFLO\Project\TCFLO\TCFLO.rst"

     X = GetVariable(f, 4)    ' calls the getvariable function with some dummy data, to test

End Sub

Private Function GetVariable(sRestartFile As String, iNumXVar As Integer) As XVDataType

    ' inumvar is 1-based
    Dim XV As XVDataType

    ' get the variable definitions
    Dim ind As Long
    Open sRestartFile For Binary As #1
    ind = 254  ' header offset

    Get #1, ind + (iNumXVar - 1) * 508 + 1, XV.iNumPoints
    Dim n As Integer
    For n = 0 To XV.iNumPoints - 1
        Get #1, ind + (iNumXVar - 1) * 508 + 9 + n * 8, XV.dData(n)
    Next n
    Get #1, ind + (iNumXVar - 1) * 508 + 459, XV.sText

    GetRestartExternalVariable = XV
    ' close the file and exit
    Close #1
    Exit Function

End Function

new, mostly not working VB.NET code

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click

        Call GetVariable( _
        "C:\Documents and Settings\crice\My Documents\Active Tasks\TCFLO\Project\TCFLO\TCFLO.rst" _
        , 4)

    End Sub

    Private Function GetVariable(ByVal sRestartFile As String, ByVal iNumXVar As Integer) As XVDataType

        Dim XV As New XVDataType

        ' get the variable definitions
        Dim ind As Long = 254   ' header offset

        If System.IO.File.Exists(sRestartFile) Then

            Dim binReader As New System.IO.BinaryReader(File.Open(sRestartFile, FileMode.Open))
            binReader.ReadBytes(ind + (iNumXVar - 1) * 508)
            XV.iNumPoints = binReader.ReadByte()     ' <---- THIS WORKS, gets the right number of points
            For n As Integer = 0 To XV.iNumPoints - 1

                XV.dData(n) = binReader.ReadSingle    ' <---- this doesn't work worth a darn
                'XV.dData(n) = binReader.ReadDouble    '    <------ this didn't work either
                'binReader.ReadBytes(8)                         '    < ------ nor this        
                'Get #1, ind + (iNumXVar - 1) * 508 + 9 + n * 8, XV.dData(n)   ' <------- the equivalent VB6.0 code

            Next n

            XV.sText = binReader.ReadChars(10)      ' <------ doesn't work


        End If

    End Function
Question by:riceman0
    LVL 11

    Expert Comment

    DO you get an error message?
    Does the binReader.Position  change after the readByte..?
    Does the ReadByte work instead of the ReadSingle at the first problem.?
    LVL 34

    Accepted Solution

    Your structure definition suggests that the data would be saved in the order sText (String - fixed length 50), then iNumPoints (Integer), then dData (Double * 51).  But your code appears to read the data in the order INumPoints, then dData, then sText.  I'm assuming that it is the latter that is correct.

    That iNumPoints is in fact the first data saved in the file structure appears to be confirmed by the fact that your VB.NET code is OK up to this point

                XV.iNumPoints = binReader.ReadByte()     ' <---- THIS WORKS, gets the right number of points

    But what you are reading is a Byte whereas what your structure appears to contain is an Integer.  An Integer, depending on its type, will be 2-, 4- or 8-bytes.  What you have read is the first 4 BITS of the data, which happens to give you the right value.  But the BinaryReader's position has only been advanced by one byte whereas the next data does not begin until after the 2-, 4- or 8-byte boundary.  So any subsequent read is going to start at the wrong place.  Which is why, I think, none of your attempts to read the next data worked.  What you need to do first, I think, is replace

                XV.iNumPoints = binReader.ReadByte()


                XV.iNumPoints = binReader.ReadInt16()
                XV.iNumPoints = binReader.ReadInt32()
                XV.iNumPoints = binReader.ReadInt64()

    as appropriate - most probably ReadInt32 as in VB.NET the default for Integer datatype is Int32.

    Then the binReader pointer should be properly aligned for starting to read the dData.  The datatype of that is Double, so

                    XV.dData(n) = binReader.ReadDouble

    should be the right call for that.

    You will, however, even if that is OK, have trouble with the VB.NET code when you get to reading sText.  This is because you are only reading - and therefore advancing binReader's pointer by - the number of Doubles that is in iNumPoints and not by the full length of the stored Array(50) of Doubles.  In your VB6 code you calculated the precise position at which the sText data would begin, but in your VB.NET code you are assuming it will start immediately after iNumPoints * Double.  But it won't (except in the case where iNumPoints = 51).  So you will need to revise your loop so that it reads 51 times (to advance the binReader pointer enough), but only stores the data in your structure until iNumPoints is reached.

    I reckon that with modifications on the above lines, your VB.NET function should work with a BinaryReader.  But an alternative approach you might like to think about is reading the whole of your file into a byte array and then extracting the individual structures from that using a similar offset calculation approach as you do in your VB6 code.  Or, you could more or less "port" your VB6 code to VB.NET by using the FileGet method instead of Get #.

    Incidentallly, your VB.NET Function doesn't return anything, but I assume that is because it is for test purposes, rather than for real.


    LVL 34

    Expert Comment

    What you have read is the first 4 BITS of the data ...

    should be

    What you have read is the first BYTE of the data ...

    LVL 85

    Expert Comment

    by:Mike Tomlinson
    Roger brings up a good point about the size of Ints being different in VB.Net.

    Important questions:

        Are you reading the OLD file created by VB6?

        ...or are you attempting to read a NEW file that was created by VB.Net code with new .Net types (and consequently new different sizes)?

    Have you considered using XML or possibly Binary Serialization instead of Structures?

    Author Comment


    To answer the questions:

    * no error messages, just wrong values
    * correct, the data in the file is not ordered like the order of the structure -- maybe a little misleading; it is # points, data, text
    * the VB.NET class is reading the exact same file as the VB6.0 class, they were both produced by the same ancient DOS program that this is post-processing  :)

    I will try the suggestions in the next couple of hours, thanks!

    Featured Post

    How to run any project with ease

    Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
    - Combine task lists, docs, spreadsheets, and chat in one
    - View and edit from mobile/offline
    - Cut down on emails

    Join & Write a Comment

    Article by: Kraeven
    Introduction Remote Share is a simple remote sharing tool, enabling you to see, add and remove remote or local shares. The application is written in VB.NET targeting the .NET framework 2.0. The source code and the compiled programs have been in…
    1.0 - Introduction Converting Visual Basic 6.0 (VB6) to Visual Basic 2008+ (VB.NET). If ever there was a subject full of murkiness and bad decisions, it is this one!   The first problem seems to be that people considering this task of converting…
    It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
    Here's a very brief overview of the methods PRTG Network Monitor ( offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

    746 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    20 Experts available now in Live!

    Get 1:1 Help Now