Click here to Skip to main content
15,885,366 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I am using VB2008.
Inherited from VB6, I have been using random access files which are really simple to use with structured data.
So I have this code below:
Dim f As Integer = FreeFile(), m As s_MailingList
FileOpen(f, MailFile, OpenMode.Random, OpenAccess.ReadWrite,OpenShare.LockRead, Len(m))
MailK = CInt(LOF(f)) \ Len(m)
ReDim Mail(MailK)
For i as Integer = 0 To MailK
   FileGet(f, Mail(i), i + 1)
Next i
FileClose(f)

it works perfectly, but I wanted to use .NET methods and this also works:
Dim fs As New FileStream(MailFile, FileMode.Open)
Using sr As New BinaryReader(fs)
   Dim b() As Byte = sr.ReadBytes(416)
'     do work to get into structure
   sr.Close()
End Using


I checked the first line and it is correct. I need to write loop etc. So I tried this based on Microsoft code as it seems simpler:

VB
Using Reader As New Microsoft.VisualBasic.FileIO.TextFieldParser(MailFile)
    Reader.TextFieldType = FileIO.FieldType.FixedWidth
    Reader.SetFieldWidths(1, 40, 40, 40, 40, 40, 40, 20, 20, 20, 20, 20, 60, 5, 4, 1, 2, 1, 1)
    Dim currentrow() As String
    While Not Reader.EndOfData
        Try
            currentrow = Reader.ReadFields()
        Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
            MsgBox(ex.Message , "is not valid and will be skipped.")
        End Try
   End While
End Using

The last code fails to read the line. The FieldWidths add up to 416.

Any ideas?
Posted
Updated 5-Apr-11 2:44am
v4
Comments
Manfred Rudolf Bihy 5-Apr-11 8:44am    
Edited: Added code tags, minor spelling and grammar improvements.

Are you sure?
Add up just the non-zero units: 1 + 5 + 4 + 1 + 2 + 1 + 1.
Do you get 16?
Because I get an odd number...
 
Share this answer
 
I wrote this which seems to work.

Public Class OpenRandomFiles
   Private fs As FileStream, sr As BinaryReader
   Friend Sub New(ByVal fPath As String)
      fs = New FileStream(fPath, FileMode.Open, FileAccess.Read, FileShare.Read)
      sr = New BinaryReader(fs)
   End Sub
   Friend Sub Dispose()
      sr.Close()
      fs.Dispose()
   End Sub
#Region " Properties "
   Private fCount As Integer
   Friend ReadOnly Property Count() As Integer
      Get
         Return fCount
      End Get
   End Property
   Private fStrings() As String
   Friend ReadOnly Property Strings() As String()
      Get
         Return fStrings
      End Get
   End Property
   Private fWidths(), wCount As Integer
   Friend WriteOnly Property Widths() As Integer()
      Set(ByVal value As Integer())
         fWidths = value
         wCount = UBound(fWidths)
         ReDim fStrings(wCount)
         Dim w As Integer = 0
         For i As Integer = 0 To wCount
            w += fWidths(i)
         Next
         fCount = CInt(fs.Length \ w - 1)
      End Set
   End Property
#End Region
   Friend Function ReadLine() As Boolean
      Try
         For i As Integer = 0 To wCount
            Dim b() As Byte = sr.ReadBytes(fWidths(i))
            fStrings(i) = ""
            For k as Integer = 0 To UBound(b)
               fStrings(i) = Chr(b(k))
            Next k
         Next
         Return False
      Catch ex As Exception
         Return True
      End Try
   End Function
End Class


It works like this
VB
Dim l() As Integer = {1, 40, 40, 40, 40, 40, 40, 20, 20, 20, 20, 20, 60, 5, 4, 1, 2, 1, 1}
Dim f As New OpenRandomFiles(MailFile)
f.Widths = l
MailK = f.Count
ReDim Mail(MailK)
For i As Integer = 0 To MailK
   f.ReadLine()
   Dim s() As String = f.Strings
   With Mail(i)
      .Flag = Asc(s(0))
      .Name = s(1)
      .Spare1 = FnAsc(s(14))
      .Spare2 = Asc(s(15))
    End With
Next
f.Dispose()
 
Share this answer
 
v6
Comments
Henry Minute 5-Apr-11 14:43pm    
Well done for persevering!
Firstly, the field widths are 415 NOT 416 as you state.
You say "The last code fails to read the line" but what does that mean? Does it show your error MessageBox or is the ReadFields() line never called, indicating that there is an EndOfData condition.

If your error box is displayed does the inner exception give more precise information about the cause?
 
Share this answer
 
OK it should be 415. The BinaryReader simply read the first character of next line.

However the parser code does not actually read the line length, presumably does the calculation itself.
The error message I get is this:-
Line 1 cannot be parsed using the current FieldWidths.

I thought maybe that fields 5, 4, 1, 2, 1, 1) contain 0s, 13s etc. which may signify end of line etc
so I changed code to
Reader.SetFieldWidths(1, 40, 40, 40, 40, 40, 40, 20, 20, 20, 20, 20, 60) thinking it would read part of the line I know is in ASCII. but it still fails. Removing the while loop so that it only reads the first line also fails.

Also the original file was written using FilePut etc.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900