Results 1 to 3 of 3

Thread: Format Byte Array

  1. #1

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Format Byte Array

    I have found this extension useful when debugging methods that use byte arrays. It was originally written to help debug TCP/IP packets and SerialPort data. This extension formats arrays of bytes, shorts, integers, and longs in binary, and optionally shows hex, decimal, and characters. The format is shown below.

    NOTE: Requires ASCIITable

    Code:
    Module FormatBytes
        'Imports System.Runtime.CompilerServices
        ''' <summary>
        ''' Takes an array and formats it for easier reading.  Shows binary by default.
        ''' </summary>
        ''' <param name="buf">the array</param>
        ''' <param name="showChar">show characters</param>
        ''' <param name="showDec">show decimal</param>
        ''' <param name="showHex">show hex</param>
        ''' <param name="dumpfile">a path string or an open IO.Stream</param>
        ''' <param name="encode">encoding - designed for 7-8 bit character sets</param>
        ''' <returns>formatted string</returns>
        ''' <remarks></remarks>
        <Extension()>
        Public Function PrettyByteBuf(buf() As Byte, _
                                      Optional showChar As Boolean = False, _
                                      Optional showDec As Boolean = False, _
                                      Optional showHex As Boolean = False, _
                                      Optional dumpfile As Object = Nothing, _
                                      Optional encode As System.Text.Encoding = Nothing) As String
            If IsNothing(buf) Then Return ""
            Dim rv As New System.Text.StringBuilder
    
            'rquires http://www.vbforums.com/showthread.php?741563-ASCII-Table
            Dim atab As ASCIITable
            If encode Is Nothing Then
                atab = New ASCIITable
            Else
                atab = New ASCIITable(encode)
            End If
    
            Dim hdrl As String = "<<--------------0---------1---------2---------3----<>---4---------5---------6---------7--->>"
            Dim dash As String = "---------------------------------------------------<>---------------------------------------"
            Dim part As Boolean = False
            Const hdrshow As Integer = 32
            For idx As Integer = 0 To buf.Length - 1 Step 8
                If idx Mod hdrshow = 0 Then
                    rv.AppendLine(hdrl)
                End If
                'newline
                rv.Append(String.Format("{0,-10}>  ", idx))
                For x As Integer = 0 To 7
                    Dim y As Integer = x + idx
                    If y >= buf.Length Then
                        part = True
                        Exit For
                    End If
                    Dim ac As ASCIITable.aChar = atab.theChars(buf(y))
                    rv.Append(String.Format("{0,-10}", ac.bin))
                Next
                If showHex Then
                    rv.AppendLine()
                    rv.Append(String.Format("{0,12}   ", "hex"))
                    For x As Integer = 0 To 7
                        Dim y As Integer = x + idx
                        If y >= buf.Length Then Exit For
                        Dim ac As ASCIITable.aChar = atab.theChars(buf(y))
                        rv.Append(String.Format("{0,-10}", ac.hex))
                    Next
                End If
                If showDec Then
                    rv.AppendLine()
                    rv.Append(String.Format("{0,12}   ", "dec"))
                    For x As Integer = 0 To 7
                        Dim y As Integer = x + idx
                        If y >= buf.Length Then Exit For
                        Dim ac As ASCIITable.aChar = atab.theChars(buf(y))
                        rv.Append(String.Format("{0,-10}", ac.code))
                    Next
                End If
                If showChar Then
                    rv.AppendLine()
                    rv.Append(String.Format("{0,12}   ", "ch"))
                    For x As Integer = 0 To 7
                        Dim y As Integer = x + idx
                        If y >= buf.Length Then Exit For
                        Dim ac As ASCIITable.aChar = atab.theChars(buf(y))
                        rv.Append(String.Format("{0,-10}", ac.ch))
                    Next
                End If
                If part Then rv.AppendLine()
                If (showChar OrElse showDec OrElse showHex) AndAlso ((idx + 8) Mod hdrshow <> 0) Then
                    If Not part Then rv.AppendLine()
                    rv.AppendLine(dash)
                Else
                    If Not part Then rv.AppendLine()
                End If
            Next
            If TypeOf (dumpfile) Is String Then
                Dim p As String = DirectCast(dumpfile, String)
                If p <> "" Then
                    rv.AppendLine()
                    rv.AppendLine()
                    Try
                        Dim txtwr As New IO.FileStream(p, FileMode.Append, FileAccess.Write, FileShare.None)
                        Dim b() As Byte = atab.encodingUsed.GetBytes(rv.ToString)
                        txtwr.Write(b, 0, b.Length)
                        txtwr.Close()
                        txtwr.Dispose()
                    Catch ex As Exception
                        Throw
                    End Try
                End If
            ElseIf TypeOf (dumpfile) Is IO.Stream Then
                Try
                    Dim txtwr As IO.Stream = DirectCast(dumpfile, IO.Stream)
                    Dim b() As Byte = atab.encodingUsed.GetBytes(rv.ToString)
                    txtwr.Write(b, 0, b.Length)
                Catch ex As Exception
                    Throw
                End Try
            End If
            Return rv.ToString
        End Function
    
        ''' <summary>
        ''' Takes an array and formats it for easier reading.  Shows binary by default.
        ''' </summary>
        ''' <param name="buf">the array</param>
        ''' <param name="showChar">show characters</param>
        ''' <param name="showDec">show decimal</param>
        ''' <param name="showHex">show hex</param>
        ''' <param name="dumpfile">a path string or an open IO.Stream</param>
        ''' <param name="encode">encoding - designed for 7-8 bit character sets</param>
        ''' <returns>formatted string</returns>
        ''' <remarks></remarks>
        <Extension()>
        Public Function PrettyByteBuf(buf() As Short, _
                                      Optional showChar As Boolean = False, _
                                      Optional showDec As Boolean = False, _
                                      Optional showHex As Boolean = False, _
                                      Optional dumpfile As Object = Nothing, _
                                      Optional encode As System.Text.Encoding = Nothing) As String
            Dim rv As New List(Of Byte)
            Dim mask As Byte = &HFF
            For Each n As Short In buf
                For x As Integer = (16 - 8) To 0 Step -8
                    rv.Add(CByte((n >> x) And mask))
                Next
            Next
            Return rv.ToArray.PrettyByteBuf(showChar, showDec, showHex, dumpfile, encode)
        End Function
    
        ''' <summary>
        ''' Takes an array and formats it for easier reading.  Shows binary by default.
        ''' </summary>
        ''' <param name="buf">the array</param>
        ''' <param name="showChar">show characters</param>
        ''' <param name="showDec">show decimal</param>
        ''' <param name="showHex">show hex</param>
        ''' <param name="dumpfile">a path string or an open IO.Stream</param>
        ''' <param name="encode">encoding - designed for 7-8 bit character sets</param>
        ''' <returns>formatted string</returns>
        ''' <remarks></remarks>
        <Extension()>
        Public Function PrettyByteBuf(buf() As Integer, _
                                      Optional showChar As Boolean = False, _
                                      Optional showDec As Boolean = False, _
                                      Optional showHex As Boolean = False, _
                                      Optional dumpfile As Object = Nothing, _
                                      Optional encode As System.Text.Encoding = Nothing) As String
            Dim rv As New List(Of Byte)
            Dim mask As Byte = &HFF
            For Each n As Integer In buf
                For x As Integer = (32 - 8) To 0 Step -8
                    rv.Add(CByte((n >> x) And mask))
                Next
            Next
            Return rv.ToArray.PrettyByteBuf(showChar, showDec, showHex, dumpfile, encode)
        End Function
    
        ''' <summary>
        ''' Takes an array and formats it for easier reading.  Shows binary by default.
        ''' </summary>
        ''' <param name="buf">the array</param>
        ''' <param name="showChar">show characters</param>
        ''' <param name="showDec">show decimal</param>
        ''' <param name="showHex">show hex</param>
        ''' <param name="dumpfile">a path string or an open IO.Stream</param>
        ''' <param name="encode">encoding - designed for 7-8 bit character sets</param>
        ''' <returns>formatted string</returns>
        ''' <remarks></remarks>
        <Extension()>
        Public Function PrettyByteBuf(buf() As Long, _
                                      Optional showChar As Boolean = False, _
                                      Optional showDec As Boolean = False, _
                                      Optional showHex As Boolean = False, _
                                      Optional dumpfile As Object = Nothing, _
                                      Optional encode As System.Text.Encoding = Nothing) As String
            Dim rv As New List(Of Byte)
            Dim mask As Byte = &HFF
            For Each n As Long In buf
                For x As Integer = (64 - 8) To 0 Step -8
                    rv.Add(CByte((n >> x) And mask))
                Next
            Next
            Return rv.ToArray.PrettyByteBuf(showChar, showDec, showHex, dumpfile, encode)
        End Function
    
        ''' <summary>
        ''' Takes an array and formats it for easier reading.  Shows binary by default.
        ''' </summary>
        ''' <param name="s">a string</param>
        ''' <param name="showChar">show characters</param>
        ''' <param name="showDec">show decimal</param>
        ''' <param name="showHex">show hex</param>
        ''' <param name="dumpfile">a path string or an open IO.Stream</param>
        ''' <param name="encode">encoding - designed for 7-8 bit character sets</param>
        ''' <returns>formatted string</returns>
        ''' <remarks></remarks>
        <Extension()>
        Public Function PrettyByteBuf(s As String, _
                                      Optional showChar As Boolean = False, _
                                      Optional showDec As Boolean = False, _
                                      Optional showHex As Boolean = False, _
                                      Optional dumpfile As Object = Nothing, _
                                      Optional encode As System.Text.Encoding = Nothing) As String
            Dim rv As New List(Of Byte)
            Dim enc As System.Text.Encoding
            If encode Is Nothing Then
                enc = System.Text.Encoding.Default
            Else
                enc = encode
            End If
            rv.AddRange(enc.GetBytes(s))
            Return rv.ToArray.PrettyByteBuf(showChar, showDec, showHex, dumpfile, encode)
        End Function
    End Module
    Sample output - note that this looks best when formatted to display with a fixed width font

    Code:
    <<--------------0---------1---------2---------3----<>---4---------5---------6---------7--->>
    0         >  00011110  00011111  00100000  00100001  00100010  00100011  00100100  00100101  
    8         >  00100110  00100111  00101000  00101001  00101010  00101011  00101100  00101101  
    16        >  00101110  00101111  00110000  00110001  00110010  00110011  00110100  00110101  
    24        >  00110110  00110111  00111000  00111001  00111010  00111011  00111100  00111101  
    <<--------------0---------1---------2---------3----<>---4---------5---------6---------7--->>
    32        >  00111110  00111111  01000000  01000001  01000010  01000011  01000100  01000101  
    40        >  01000110  01000111  01001000  01001001  01001010  01001011  01001100  01001101  
    48        >  01001110  01001111  01010000  01010001  01010010  01010011  01010100  01010101  
    56        >  01010110  01010111  01011000  01011001  01011010

    Code:
    <<--------------0---------1---------2---------3----<>---4---------5---------6---------7--->>
    0         >  00011110  00011111  00100000  00100001  00100010  00100011  00100100  00100101  
             hex   1E        1F        20        21        22        23        24        25        
             dec   30        31        32        33        34        35        36        37        
              ch   *RS       *US       *SPC      !         "         #         $         %         
    ---------------------------------------------------<>---------------------------------------
    8         >  00100110  00100111  00101000  00101001  00101010  00101011  00101100  00101101  
             hex   26        27        28        29        2A        2B        2C        2D        
             dec   38        39        40        41        42        43        44        45        
              ch   &         '         (         )         *         +         ,         -         
    ---------------------------------------------------<>---------------------------------------
    16        >  00101110  00101111  00110000  00110001  00110010  00110011  00110100  00110101  
             hex   2E        2F        30        31        32        33        34        35        
             dec   46        47        48        49        50        51        52        53        
              ch   .         /         0         1         2         3         4         5         
    ---------------------------------------------------<>---------------------------------------
    24        >  00110110  00110111  00111000  00111001  00111010  00111011  00111100  00111101  
             hex   36        37        38        39        3A        3B        3C        3D        
             dec   54        55        56        57        58        59        60        61        
              ch   6         7         8         9         :         ;         <         =         
    <<--------------0---------1---------2---------3----<>---4---------5---------6---------7--->>
    32        >  00111110  00111111  01000000  01000001  01000010  01000011  01000100  01000101  
             hex   3E        3F        40        41        42        43        44        45        
             dec   62        63        64        65        66        67        68        69        
              ch   >         ?         @         A         B         C         D         E         
    ---------------------------------------------------<>---------------------------------------
    40        >  01000110  01000111  01001000  01001001  01001010  01001011  01001100  01001101  
             hex   46        47        48        49        4A        4B        4C        4D        
             dec   70        71        72        73        74        75        76        77        
              ch   F         G         H         I         J         K         L         M
    Last edited by dbasnett; May 25th, 2015 at 11:04 AM.

  2. #2
    Karen Payne MVP kareninstructor's Avatar
    Join Date
    Jun 2008
    Location
    Oregon
    Posts
    6,713

    Re: Format Byte Array

    Here is a VS2012 Console project ready to run.
    Last edited by kareninstructor; Nov 6th, 2013 at 11:38 AM. Reason: Changed project link to updated version

  3. #3

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Format Byte Array

    The code was modified in place to fix a few formatting errors and added the ability to dump the result to a file, which required a change to ASCIITable (make sure you have the latest version).

    If the extension is passed a path string for the dump file it opens the file, appends the formatted string, and closes the file.

    If the extension is passed an IO.Stream for the dump file it appends the formatted string. The IO.Stream must be open.

    Also added support to dump strings.

    Code:
            Dim theChars As String = "Test ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            '
            RichTextBox1.Text = (theChars & vbCrLf).PrettyByteBuf(True)
    results in
    Code:
    <<--------------0---------1---------2---------3----<>---4---------5---------6---------7--->>
    0         >  01010100  01100101  01110011  01110100  00100000  01000001  01000010  01000011  
              ch   T         e         s         t         *SPC      A         B         C         
    ---------------------------------------------------<>---------------------------------------
    8         >  01000100  01000101  01000110  01000111  01001000  01001001  01001010  01001011  
              ch   D         E         F         G         H         I         J         K         
    ---------------------------------------------------<>---------------------------------------
    16        >  01001100  01001101  01001110  01001111  01010000  01010001  01010010  01010011  
              ch   L         M         N         O         P         Q         R         S         
    ---------------------------------------------------<>---------------------------------------
    24        >  01010100  01010101  01010110  01010111  01011000  01011001  01011010  00001101  
              ch   T         U         V         W         X         Y         Z         *CR       
    <<--------------0---------1---------2---------3----<>---4---------5---------6---------7--->>
    32        >  00001010  
              ch   *LF       
    
    ---------------------------------------------------<>---------------------------------------
    Last edited by dbasnett; Nov 7th, 2013 at 10:17 AM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

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