Hello,
I have Get() & Put() functions in my VB6 project. It was upgraded to FileGet() & FilePut() but they are not working. I am getting the runtime error as "Unable to read beyond the end of the stream."
Eg: FileGet(X, Y, Z) -> I think the parameters are FileGet(FileNumber, Value, RecordNumber). Same for FilePut().
Please inform me how I can change this to make it work in VB.Net.
Regards,
Simran Kaur.

Dani AI

Generated

the VB6 DAT files you are reading were almost certainly written as fixed-length records in Random mode. The .NET compatibility methods still work the same way, but only if you keep the same mode and record size. In Random mode the 3rd argument to FileGet/FilePut is a 1-based record number and the record length is the Len you passed to FileOpen; in Binary mode the 3rd argument is a byte offset and the Len you passed is ignored. So switching Random -> Binary will break your layout and can trigger "Unable to read beyond the end of the stream." Keep Random and the exact record length. FileOpen and FileGet.

Minimal-change recipe for VB6-style UDTs:

  • Declare fixed-length fields as String with VBFixedString (avoid Char()) so Len(TopDataType) matches the bytes on disk.
  • VBFixedArray does not allocate memory; you still ReDim before FileGet. VBFixedStringAttribute and VBFixedArrayAttribute.
Structure TopDataType
  <VBFixedString(40)> Public TopName As String
  <VBFixedString(12)> Public TopDate As String
  <VBFixedString(40)> Public TopJobName As String
  Public ExcelRecord As Short
  <VBFixedString(40)> Public DataSheet As String
  Public Catagory As Short
  <VBFixedArray(19)> Public TopProperties() As Short
  Public Status As Short
  Public Deleted As Short
  <VBFixedString(100)> Public Extra As String
  Public Sub Init() : ReDim TopProperties(19) : End Sub
End Structure

Dim ff = FreeFile()
Dim rec As New TopDataType : rec.Init()
FileOpen(ff, "ABC.DAT", OpenMode.Random, OpenAccess.ReadWrite, , Len(rec))
Dim count As Integer = LOF(ff) \ Len(rec)  'number of records
If count >= 1 Then FileGet(ff, rec, 1)     'read record 1 (1-based)
FileClose(ff)

Notes that address replies above:

  • is right that StreamReader/Writer are great for text, but they will not preserve fixed-length binary UDT layouts. Use them only if you redesign the file format. Writing to files in VB.
  • Prefer iterating 1 To count rather than Do While Not EOF. In Random/Binary, EOF becomes True only after a read fails, which can mask off-by-one errors. EOF function.
  • If you ever read or write a standalone fixed-length String (not inside a Structure), use the StringIsFixedLength argument on FileGet/FilePut to match VB6 fixed strings. FileGet, FilePut.

Recommended Answers

All 7 Replies

You should look into the uses of StreamReader and StreamWriter.

'Reading files
Private Sub ReadFile(Filename As String)
   Dim stream As New IO.FileStream(Filename, IO.FileMove.Open)
   Dim sr As New IO.StreamReader(stream)
   Dim line As String = ""

   While sr.Peek <> -1  'Read until EOF
      line = sr.ReadLine
   End While
   sr.Close()
   stream.Close()
End Sub

'Writing to files
Private Sub WriteFile(Filename As String)
   Dim stream As New IO.FileStream(Filename, IO.FileMode.Create)
   Dim sw As New IO.StreamWriter(stream)

   sw.WriteLine("Here's some text to write on a line") 'Automatic linebreak in file
   sw.Flush()
   sw.Close
   stream.Close()
End Sub
commented: was helpful +1

Hello,
The VB prj has structures. These structures are stored in the files using get() & put(). I dont want to change lot of code. Is it possible to make minimum changes to do the required saving & retrieving using the exisiting code? I am posting an example code below;
------------------------------------------------------------------
In Module:
Structure HistoricalDataType
'UPGRADE_WARNING: Fixed-length string size must fit in the buffer.
<VBFixedString(40),System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray,SizeConst:=40)> Public TopName() As Char 'TopData.HDName

'UPGRADE_WARNING: Fixed-length string size must fit in the buffer.
<VBFixedString(12),System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray,SizeConst:=12)> Public TopDate() As Char 'TopData.JobDate

'UPGRADE_WARNING: Fixed-length string size must fit in the buffer.
<VBFixedString(40),System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray,SizeConst:=40)> Public TopJobName() As Char 'TopData.ExcelJobName

Dim ExcelRecord As Short 'TopData.ExcelRecord

'UPGRADE_WARNING: Fixed-length string size must fit in the buffer.
<VBFixedString(40),System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray,SizeConst:=40)> Public DataSheet() As Char 'TopData.DataSheet

Dim Catagory As Short 'TopData.Catagory

<VBFixedArray(19)> Dim TopProperties() As Short 'TopData.TopProperties(0 To 19)

Dim Status As Short 'TopData.Status

Dim Deleted As Short 'TopData.Deleted

'UPGRADE_WARNING: Fixed-length string size must fit in the buffer.
<VBFixedString(100),System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray,SizeConst:=100)> Public Extra() As Char 'TopData.Extra

'UPGRADE_TODO: "Initialize" must be called to initialize instances of this structure.
Public Sub Initialize()
ReDim TopProperties(19)
End Sub

End Structure
---------------------
In Form1:
Private Sub TopDataSave()

Dim TopData As TopDataType 'Above Structure

shtFF = FreeFile
strMyDataFile = My.Application.Info.DirectoryPath & "\MY DATA FILE\MyDataFile.DAT"
FileOpen(FF, strMyDataFile, OpenMode.Random, , , Len(TopData))
TopRecords = LOF(FF) \ Len(TopData)

If TopRecords > 0 Then
'
For Rec = 1 To TopRecords
'UPGRADE_WARNING: Get was upgraded to FileGet and has a new behavior.
FileGet(FF, TopData, Rec)
'
If TopData.Deleted = True Then
TopData.ExcelRecord = 0
TopData.DataSheet = ""
TopData.TopName = ""
TopData.TopDate = ""
TopData.ExcelJobName = ""
TopData.PipeRecap = ""
TopData.Catagory = 0
'
For X = 0 To 19
TopData.TopProperties(X) = 0
Next X
'
TopData.Catagory = 0
TopData.Status = 0
'
'UPGRADE_WARNING: Put was upgraded to FilePut and has a new behavior.
FilePut(FF, TopData, Rec)
End If
'
Next Rec
'
End If
'
FileClose(FF))
End Sub
----------------------------------------------------------------------------
pls help me in this matter.
Regards,
Simran Kaur.

In the above code the structure's name is TopDataType.

Ah. Now I see.
Ok, try this:

If TopRecords > 0 Then
   Rec = 1
   Do While Not EOF(FF)  '<<--- Replace the For loop with this While loop
      'UPGRADE_WARNING: Get was upgraded to FileGet and has a new behavior. 
      FileGet(FF, TopData, Rec) 
      '
      If TopData.Deleted = True Then
         TopData.ExcelRecord = 0
         TopData.DataSheet = ""
         TopData.TopName = ""
         TopData.TopDate = ""
         TopData.ExcelJobName = ""
         TopData.PipeRecap = ""
         TopData.Catagory = 0
         '
         For X = 0 To 19
            TopData.TopProperties(X) = 0
         Next X
         '
         TopData.Catagory = 0
         TopData.Status = 0
         '
         'UPGRADE_WARNING: Put was upgraded to FilePut and has a new behavior. 
         FilePut(FF, TopData, Rec)
      End If
      '
      Rec += 1
   Loop
End If
commented: was very helpful & thoughtful +1

Hello,
Thanks for your solution. It was helpful. How can I use the above code for the below example?
FileOpen(1, "ABC.DAT", OpenMode.Random, , , Len(TOPFILE))
Records = LOF(1) \ Len(TOPFILE)
FileGet(1, TOPFILE, 1)
FileClose(1)

Here the error is "Unable to read beyond the end of the stream." and "EndOfStreamException was unhandled." though there are 5 records. The error msg window shows nothing & zeroes in the 'TOPFILE' data for the first record.

Even if I change it to
Dim FF As Short = FreeFile() 'MyCode changed 1 to FF
FileOpen(FF, "ABC.DAT", OpenMode.Binary, , , Len(TOPFILE))
Records = LOF(FF) \ Len(TOPFILE)
Do While Not EOF(FF)
FileGet(FF, TOPFILE, Records)
Loop
FileClose(FF)

the error persists.

Also what is the difference between Open.Random & Open.Binary. As FileGet & FilePut were not working, I converted Open.Random to Open.Binary. Now the file is saving in FilePut() but retrieving the existing files in .dat format is not possible in FileGet(). What should be done? How can old .dat files be converted to Binary format files?
Regards,
Simran.

I don't know how they can be magically converted to binary on their own.
If you create and save a file in Random mode, then they should be read in Random mode. Also, if you create and save in Binary mode, then you should read them in Binary mode.

However, perhaps the error is occuring because of Records = LOF(FF) | Len(TOPFILE).
Consider the fact that the length of some objects has a zero-based index.
So, the line could be rewritten as: Records = (LOF(FF) | Len(TOPFILE)) - 1

Hello O2,
Thanks for replying with patience. I will consider the factor about zero base.
Regards,
Simran.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.