Random File IO In VB 2008
Random File IO In VB 2008
Random File IO In VB 2008
Random File IO In VB 2008
Random File IO In VB 2008
Random File IO In VB 2008 Random File IO In VB 2008 Random File IO In VB 2008 Random File IO In VB 2008 Random File IO In VB 2008 Random File IO In VB 2008 Random File IO In VB 2008 Random File IO In VB 2008
Random File IO In VB 2008 Random File IO In VB 2008
Random File IO In VB 2008
Go Back  Xtreme Visual Basic Talk > > > Random File IO In VB 2008


Reply
 
Thread Tools Display Modes
  #1  
Old 02-28-2012, 01:51 PM
unclebill unclebill is offline
Junior Contributor
 
Join Date: Apr 2003
Location: San Diego, CA
Posts: 308
Default Random File IO In VB 2008


I have managed to learn a little of VB 2008 but I'm still struggling. I managed to convert one VB6 program to VB .net but all the file IO in it is sequential access.

I'm trying to convert a VB6 program to .net. This program uses almost entirely random file IO.

In one of the books I have, I found an example which, with a minor mod worked. I tried using that code to modify my program and it does not work. In my code, the FileGet results in the obj containing null strings. Yet in the sample program using the same structure, the obj contains actual data.

The file is being opened because the record count is calculated correctly [iUpper = LOF(F_Trk) / TrkLen].

I used a Type in VB6 which I converted to a Structure in VB 2008. The function in which the problem occurs is below as well as the Structure declaration and the Function it calls (PAB) which is a derivation of the PathAddBackslash API call.

Is there an easier, more efficient way to achieve the same results in VB .NET?

If someone can point out the error I would sincerely appreciate it. I have noted the lines added/changed in the .NET adaptation.
Code:
Public Class Form1
    Public Function GetTrkName(ByVal TrkID As String) As String
        Dim bFind As Boolean, F_Trk As Integer, iLower As Integer, iPtr As Integer, iRcdPtr As Integer, _
            iUpper As Integer, sID As String, TrkLen As Integer
        Dim Track As New Trk
        Dim obj As ValueType = DirectCast(Track, ValueType) '.NET mod
        TrkLen = Len(Track)
        sID = UCase(Trim(TrkID))
        If Dir(PAB(System.Reflection.Assembly.GetExecutingAssembly.Location()) & "Tracks.dat") = "" Then
            GetTrkName = TrkID
            Exit Function
        End If
        F_Trk = FreeFile()
        FileOpen(F_Trk, PAB(System.Reflection.Assembly.GetExecutingAssembly.Location()) & "Tracks.dat", OpenMode.Random)
        iLower = 1
        iUpper = LOF(F_Trk) / TrkLen
        iRcdPtr = (iLower + iUpper) \ 2
        '   Execute a 5 step binary search of the Tracks.dat file. A 5-step _
        'binary search on a list of 400 items narrows the sequential _
        'search to a list of about 12 items greatly reducing the search time
        For iPtr = 1 To 5
            'Get F_Trk, iRcdPtr, Track           'VB 6 code
            FileGet(F_Trk, obj, iRcdPtr)     '.NET mod
            Track = DirectCast(obj, Trk)     '.NET mod
            If sID = Trim(Track.TrkID) Then
                bFind = True    'If binary search finds track name, set flag to stop search
                Exit For
            End If
            If sID > Trim(Track.TrkID) Then
                iLower = iRcdPtr
            Else
                iUpper = iRcdPtr
            End If
            iRcdPtr = (iLower + iUpper) \ 2
        Next
        '   If track name not found in binary search, start sequential search over a finite range within the file.
        If Not bFind Then
            For iRcdPtr = iLower To iUpper
                FileGet(F_Trk, Track, iRcdPtr)
                If sID = Trim(Track.TrkID) Then
                    bFind = True    'If track name found, set flag.
                    Exit For
                End If
            Next
        End If
        If bFind Then
            '   If track name found, return track name
            GetTrkName = Trim(Track.TrkName)
        Else
            '   Otherwise, return track code in place of track name
            GetTrkName = Trim(TrkID)
            Track.TrkLevel = "0"
        End If
        FileClose(F_Trk)
    End Function

    Public Function PAB(ByVal Path As String) As String
        Dim Ptr As Int16, Tmp As String
        Ptr = InStrRev(Path, "\")
        Tmp = Microsoft.VisualBasic.Left(Path, Ptr)
        If Microsoft.VisualBasic.Right(Tmp, 1) = "\" Then
            PAB = Tmp
        Else
            PAB = Tmp & "\"
        End If
    End Function

    Public Structure Trk
        <VBFixedStringAttribute(3)> Public TrkID As String      'Track ID Code
        <VBFixedStringAttribute(23)> Public TrkName As String   'Track name
        <VBFixedStringAttribute(1)> Public TrkLevel As String   'Track level
        <VBFixedStringAttribute(2)> Public Shared EoR As String = vbCrLf    'End of Record: vbCRLF to make file viewable in Notepad
    End Structure

End Class
As an aside question, the sample code from which I got this in its original form raised an error in this line.
Code:
For Each i As Integer In New Integer() (3, 1, 5, 2, 6)
Can someone explain what caused the error and the correction for it? The "3" is marked with the error indicator and the message displayed when the mouse cursor hovers is: Bounds can be specified only for the top-level array when initializing an array of arrays
Reply With Quote
  #2  
Old 03-03-2012, 10:20 PM
passel's Avatar
passelRandom File IO In VB 2008 passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,028
Default

I believe
(3, 1, 5, 2, 6)
should have been in curly brackets
{3, 1, 5, 2, 6}

I'm mostly familiar with VB6 and earlier, and since you are using FileOpen, you are using the VB6 style file access.
I noticed you didn't specify the record length when you opened the file.
In VB6 and earlier, if you didn't specify the record length then the size would default to 128 bytes.
It looks like your desired record size should be 29 bytes, based on your structure.
But, if you put a breakpoint on the line after you set TrkLen and look at the value that TrkLen is set to, you will see that it is 27.
The reason it is 27 has you marked the last two byte field as being shared, which means that it is common to all instances of that structure, so is technically not part of any one of them.
So, only the none shared fields are part of a given instance, and only those fields are written to the file (and read from the file).

To get the 29 bytes written and read from the file you can't have the last field shared.
If you want it to be CR/LF when written, then you will need to initialize it when you create the instance, or at some point before you write the data to the file.

Since you are using TrkLen to calculate how many records are in the file, then make sure you specify that length when you open the file, or you won't be aligned at all, and you will be getting garbage or nothing.
FileOpen(F_Trk, PAB(System.Reflection.Assembly.GetExecutingAssembly.Location()) & "Tracks.dat", OpenMode.Random, , ,TrkLen)

Also DirectCasting Track back and forth to obj As ValueType seems to be unecessary.
I used Track directly in both FilePut and FileGet operations without problem.

The code seemed to work fine for me after I made the above changes.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 03-03-2012 at 11:28 PM.
Reply With Quote
  #3  
Old 03-04-2012, 01:53 AM
unclebill unclebill is offline
Junior Contributor
 
Join Date: Apr 2003
Location: San Diego, CA
Posts: 308
Default Thanks very much for the help.

After looking up endless references on line, I finally found the syntax for FileOpen with the record length parameter. I modified my code for the primary function as below and it did work:
Code:
    Public Function GetTrkName(ByVal TrkID As String) As String
        Dim bFind As Boolean, F_Trk As Integer, iLower As Integer, iPtr As Integer, iRcdPtr As Integer, _
            iUpper As Integer, sID As String
        sID = UCase(Trim(TrkID))
        If Dir(PAB(System.Reflection.Assembly.GetExecutingAssembly.Location()) & "Tracks.dat") = "" Then
            GetTrkName = TrkID
            Exit Function
        End If
        F_Trk = FreeFile()
        FileOpen(F_Trk, PAB(System.Reflection.Assembly.GetExecutingAssembly.Location()) & _
            "Tracks.dat", OpenMode.Random, , , TrkLen)
        iLower = 1
        iUpper = LOF(F_Trk) / TrkLen
        iRcdPtr = (iLower + iUpper) \ 2
        '   Execute a 5 step binary search of the Tracks.dat file. A 5-step binary search on a list _
        'of 400 items narrows the sequential search to a list of about 12 items greatly reducing the search time_
        For iPtr = 1 To 5
            FileGet(F_Trk, Track, iRcdPtr)
            Call Application.DoEvents()
            If sID = Trim(Track.TrkID) Then
                bFind = True    'If binary search finds track name, set flag to stop search
                Exit For
            End If
            If sID > Trim(Track.TrkID) Then
                iLower = iRcdPtr
            Else
                iUpper = iRcdPtr
            End If
            iRcdPtr = (iLower + iUpper) \ 2
        Next
        '   If track name not found in binary search, start sequential search over a finite range within the file.
        If Not bFind Then
            For iRcdPtr = iLower To iUpper
                FileGet(F_Trk, Track, iRcdPtr)
                Call Application.DoEvents()
                If sID = Trim(Track.TrkID) Then
                    bFind = True    'If track name found, set flag.
                    Exit For
                End If
            Next
        End If
        If bFind Then
            '   If track name found, return track name
            GetTrkName = Trim(Track.TrkName)
        Else
            '   Otherwise, return track code in place of track name
            GetTrkName = Trim(TrkID)
            Track.TrkLevel = "0"
        End If
        FileClose(F_Trk)
    End Function
Thanks for the information on the problem with TrkLen being incorrectly calculated. After I changed the Structure so the EoR was not shared and initialized it in the form_load event, that resolved the other problem.

However, I found I had to add the line:
Code:
Call Application.DoEvents()
in order to get the data to be placed in the structure Track. I had notice stepping thru the code earlier that the structure didn't appear to be updated until a couple of lines after the FileGet statement and just took a shot at DoEvents and got lucky. Without the DoEvents() statement, the If statement was comparing on the Track structure from the previous FileGet. Any ideas on why that was happening?

I also went back to the sample program, and sure enough, changing the () to {} solved the problem with that program. Thanks much. It's nice to know why the error occurred. I went back to the book and the structure still looked like () until I got out my magnifying glass. Then I could tell the marks were actually {}.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
Random File IO In VB 2008
Random File IO In VB 2008
Random File IO In VB 2008 Random File IO In VB 2008
Random File IO In VB 2008
Random File IO In VB 2008
Random File IO In VB 2008 Random File IO In VB 2008 Random File IO In VB 2008 Random File IO In VB 2008 Random File IO In VB 2008 Random File IO In VB 2008 Random File IO In VB 2008
Random File IO In VB 2008
Random File IO In VB 2008
 
Random File IO In VB 2008
Random File IO In VB 2008
 
-->