2 people like it.

hexdump (somewhat fast)

Simple functions to display a hex dump of a byte array using sequence expressions, with ASCII. Rewrote naive version that used string concat, based on optimizations in http://fssnip.net/ht, and cleaned up ASCII formatting.

Hex dump of byte array b, display width w.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
// Without ASCII column.

let hexdump w (b : byte[]) =
    seq {
        for i in 0..w..b.Length - 1 ->
            let hex = 
                Seq.skip i b 
                |> Seq.truncate w
                |> Seq.map (sprintf "%02X ")
                |> Seq.fold ( + ) ""
            sprintf "%08X  %s\n" i hex  
        }
    |> Seq.iter (printf "%s")

(Formatting helper functions omitted.)

// With ASCII column.

let hexdump' w (b : byte[]) =
    seq {
        for i in 0..w..b.Length - 1 ->
            let byt = Seq.skip i b 
                      |> Seq.truncate w
            let hex = Seq.map (sprintf "%02X ") byt
                      |> Seq.fold ( + ) "" 
                      |> pad w
            let asc = Seq.map (fun c -> sprintf "%c" (filterChar c)) byt 
                      |> Seq.fold ( + ) "" 
            sprintf "%08X  %s %s\n" i hex asc   
        }
    |> Seq.iter (printf "%s")

// Example output in FSI:
//> hexdump 16 someBytes;;
//00000000  92 36 81 DC 1F F0 87 1F 49 93 8F D3 6C 31 22 71 
//00000010  4F 2E BE C5 8D 5D D1 E6 0F 6A 2B D5 4A 8C 53 B7 
//00000020  01 69 E7 
//val it : unit = ()
//
//> hexdump' 16 someBytes;;
//00000000  49 AA 22 B2 F5 19 FC 48 C5 F9 1F 96 3C C7 53 C8  I."....H....<.S.
//00000010  75 4E 1E 3B 1F 6E CD 68 AB F6 63 FC 80 25 55 A5  uN.;.n.h..c..%U.
//00000020  6C F3 8E 2E FB E3 A4 D3 21 E7 EE 50 0B 1F 9C     l.......!..P...
//val it : unit = ()
val hexdump : w:int -> b:byte [] -> unit

Full name: Script.hexdump
val w : int
val b : byte []
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.byte

--------------------
type byte = System.Byte

Full name: Microsoft.FSharp.Core.byte
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val i : int
property System.Array.Length: int
val hex : string
module Seq

from Microsoft.FSharp.Collections
val skip : count:int -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.skip
val truncate : count:int -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.truncate
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val fold : folder:('State -> 'T -> 'State) -> state:'State -> source:seq<'T> -> 'State

Full name: Microsoft.FSharp.Collections.Seq.fold
val iter : action:('T -> unit) -> source:seq<'T> -> unit

Full name: Microsoft.FSharp.Collections.Seq.iter
val printf : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printf
// Filters non-printable characters.
let filterChar (b : byte) = if int b <= 32 || int b > 127 then '.' else char b

// Pads a string based on number (w) of bytes to display.
let pad w (s : string) =
    let t = (w * 2) + w
    if s.Length < t then s + String.replicate (t - s.Length) " " else s
val hexdump' : w:int -> b:byte [] -> unit

Full name: Script.hexdump'
val byt : seq<byte>
val pad : w:int -> s:string -> string

Full name: Script.pad
val asc : string
val c : byte
val filterChar : b:byte -> char

Full name: Script.filterChar
Next Version Raw view Test code New version

More information

Link:http://fssnip.net/hq
Posted:11 years ago
Author:Matthew H. Traylor
Tags: hex dump , hex , sequences , conversion