Results 1 to 11 of 11

Thread: [RESOLVED] Reading a structure from a file.

  1. #1

    Thread Starter
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Resolved [RESOLVED] Reading a structure from a file.

    I have several quesions about reading/writing structures from/to files.
    In a scenario when I open a data file having its own header and variable data fields I create a structure that represents a header consisting of 9 bytes:

    Code:
    Public Structure HeaderInfo
         Public DataField1 As Integer
         Public DataField2 As Byte
         Public DateField3 As Integer
    End Structure
    I'm using this code for the time being:

    vb.net Code:
    1. Public Function ReadHeader(ByVal FileName As String) As HeaderInfo
    2.     Dim ReturnInfo As HeaderInfo
    3.     Try
    4.         Using br As New IO.BinaryReader(New IO.FileStream(FileName, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read))
    5.             With ReturnInfo
    6.                 .DataField1 = br.ReadInt32()
    7.                 .DataField2 = br.ReadByte()
    8.                 .DataField3 = br.ReadInt32()
    9.             End With
    10.             br.Close()
    11.         End Using
    12.         Return ReturnInfo
    13.     Catch ex As Exception
    14.         Return Nothing
    15.     End Try
    16. End Function

    The first question is - can I fill the structure directly somehow? Some structures are very long and filling them this way will be tedious. For example, if I know the length of the structure I could read the needed number of bytes in a byte array and somehow marshal these bytes into the structure.

    My second question:
    I can use Marshal.PtrToStructure, but then I would need to get an IntPtr of my byte array. Is it the only option?

    And the last question - I use <Serializable()> attribute for my structure. Am I doing it right? Should there be some other attributes?

  2. #2
    Fanatic Member stlaural's Avatar
    Join Date
    Sep 2007
    Location
    Quebec, Canada
    Posts
    683

    Re: Reading a structure from a file.

    That would have been much easier in C++ I'm afraid there's no simple solution for this problem, well at least no simple solution known to me.

    Here's a post about that issue, it might help at least a little.

    good luck
    Alex
    .NET developer
    "No. Not even in the face of Armageddon. Never compromise." (Walter Kovacs/Rorschach)

    Things to consider before posting.
    Don't forget to rate the posts if they helped and mark thread as resolved when they are.


    .Net Regex Syntax (Scripting) | .Net Regex Language Element | .Net Regex Class | DateTime format | Framework 4.0: what's new
    My fresh new blog : writingthecode, even if I don't post much.

    System: Intel i7 920, Kingston SSDNow V100 64gig, HDD WD Caviar Black 1TB, External WD "My Book" 500GB, XFX Radeon 4890 XT 1GB, 12 GBs Tri-Channel RAM, 1x27" and 1x23" LCDs, Windows 10 x64, ]VS2015, Framework 3.5 and 4.0

  3. #3
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: Reading a structure from a file.

    If you've got the Serializable tag on your structure...then yes, you are doing it the hard way and not taking advantage of that tag.

    Here's one example:
    http://www.vbforums.com/showthread.p...=serialization
    It's using XML serialization.

    doing binary serialization is just as easy, all you need is a binary stream instead of an xml one.

    In fact, if you do a search here in the VS2005/2008/2010 forums for "serialization" you'll find a ton of threads and examples.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  4. #4

    Thread Starter
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Reading a structure from a file.

    Well, I've changed the function like this:

    Code:
    Public Function GetCellInfo(ByVal Offset As Long) As CellInfo
        Using br As New IO.BinaryReader(New IO.FileStream(_filename, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read))
            br.BaseStream.Position = Offset
            Dim bytes() = br.ReadBytes(32)
            Dim handle As IntPtr = Marshal.ReadIntPtr(bytes, 0)
            Dim ci As New CellInfo
            Marshal.PtrToStructure(handle, ci)
            If _header.FormatVersion = 6 Then
                ci.TextRotation = 0
            End If
            Return ci
        End Using
    End Function
    The structure length is 32 bytes and I use these attributes.
    Code:
    <StructLayout(LayoutKind.Sequential), Serializable()> _
    Public Structure CellInfo
       ' ...
    End Structure
    Didn't test it though, so I don't know whether it works.

  5. #5
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: Reading a structure from a file.

    Do you want to use the fairly simple serialization or do you want to continue to push the data in and out of the file your own way?
    Simple binary serialization....
    Code:
            Dim someClassOfMine As New TestClass1
            Dim formatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
            Dim myWriter As New IO.FileStream("arrayTest.bin", IO.FileMode.Create)
            formatter.Serialize(myWriter, someClassOfMine)
            myWriter.Close()
    Use your structure instead of the class I used...

    And to deserialize...
    Code:
            Dim formatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
            Dim fs As New IO.FileStream("arrayTest.bin", IO.FileMode.Open)
            someClassOfMine = DirectCast(formatter.Deserialize(fs), TestClass1)
            fs.Close()
    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  6. #6

    Thread Starter
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Reading a structure from a file.

    No, I don't think this is the case of mine.
    The file I try to open is a custom spreadsheet format. It hold the following structures:

    Header ' Fixed length
    General Cell Format ' Fixed length
    Font Table ' Variable Length
    Page Header ' Fixed length
    Pfge Footer ' Fixed Length
    Columns definitions ' Variable length
    Rows definitions ' Variable length
    Rows data ' variable length
    Groups definitions ' Variable length
    Range names ' Variable length

    So I doublt I can use your example.

  7. #7
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: Reading a structure from a file.

    That sound you are hearing is me banging my head into the desk. It's that kind of info that's needed in the first post so that you don't get a bad answer. Since that is the case... serialization does you zero good, and there's no point in having the Serialization mark up. It also means you are basically relegated to using your current brute force method (of which there isn't anything inherently wrong with). But like you mentioned, it can be tedious.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  8. #8

    Thread Starter
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Reading a structure from a file.

    Quote Originally Posted by techgnome View Post
    That sound you are hearing is me banging my head into the desk. It's that kind of info that's needed in the first post so that you don't get a bad answer. Since that is the case... serialization does you zero good, and there's no point in having the Serialization mark up. It also means you are basically relegated to using your current brute force method (of which there isn't anything inherently wrong with). But like you mentioned, it can be tedious.

    -tg
    Oddly enought I'm not hearing any sounds right now

    Well, the question gradually transforms into 'How can I cast a byte array into a structure and back?' I've no chance to test the code from my post #4 right now but if it works I think the matter is resolved. Unfortunately I would be able to test it only tomorrow morning ))) If this method fails I'm thinking of resorting to the CopyMemory API function.

  9. #9
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Re: Reading a structure from a file.

    It's tedious?
    That's what With is for. Just use the simple way, and keep the code readable.

  10. #10
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: Reading a structure from a file.

    It's still 200 lines of code for 200 fields... that's where the tedium is.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  11. #11

    Thread Starter
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Reading a structure from a file.

    Finally got it working:

    vb.net Code:
    1. Dim bytes() = br.ReadBytes(60) ' Reading 60 bytes from the file
    2. Dim handle As IntPtr
    3. Dim gch = GCHandle.Alloc(bytes, GCHandleType.Pinned) ' Allocating a handle to unmanaged memory area
    4. handle = gch.AddrOfPinnedObject ' Obtaining a pointer to it
    5.  
    6. ' Filling the structure:
    7. Dim lf As LOGFONT = CType(Marshal.PtrToStructure(handle, GetType(LOGFONT)), LOGFONT)
    8.  
    9. ' Releasing the handle
    10. gch.Free()

    Logfont structure:

    Code:
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
        Public Structure LOGFONT
            Public lfHeight As UInt32                                   ' 4 bytes (offset 0)
            Public lfWidth As UInt32                                    ' 4 bytes (offset 4)
            Public lfEscapement As UInt32                               ' 4 bytes (offset 8)
            Public lfOrientation As UInt32                              ' 4 bytes (offset 12)
            Public lfWeight As UInt32                                   ' 4 bytes (offset 16)
            Public lfItalic As Byte                                     ' 1 byte  (offset 20)
            Public lfUnderline As Byte                                  ' 1 byte  (offset 21)
            Public lfStrikeOut As Byte                                  ' 1 byte  (offset 22)
            Public lfCharSet As Byte                                    ' 1 byte  (offset 23)
            Public lfOutPrecision As Byte                               ' 1 byte  (offset 24)
            Public lfClipPrecision As Byte                              ' 1 byte  (offset 25)
            Public lfQuality As Byte                                    ' 1 byte  (offset 26)
            Public lfPitchAndFamily As Byte                             ' 1 byte  (offset 27)
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)> _
            Public lfFaceName As String                                 ' 32 bytes(offset 28) total 60 bytes
        End Structure

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width