Guru: Legible Hexadecimal
August 28, 2017 Ted Holt
Since I am a normal red-blooded human being, I try to make life as easy as possible for myself. I don’t do very well in general, but occasionally I manage to afford myself a bit of comfort. Recently I had to deal with long strings of hexadecimal digits. Trying to read that stuff was more than I could deal with, so I wrote a function to help me.
It’s easy to think of hexadecimal literal as strings because they contain the letters A through F. However, they are not strings, but numbers. We use the letters A through F for the highest digits of the base 16 number system, but we could just as easily use any other six symbols, even symbols that no one has invented.
To make decimal numbers easier to read, we use editing characters. In the United States of America, those editing characters would be the period, which serves as a decimal point, and the comma, which separates groups of three digits left of the decimal point. Other nations have other conventions.
In the same way, we can edit hexadecimal numbers. One common method of hexadecimal editing is to divide the hex literal into groups of two hex digits. Each group represents one byte. I wrote a SQL function to display a hexadecimal number in that format. I call it LegibleHex.
Here’s the way the SQL HEX function, which comes as part of DB2, displays the hexadecimal representation of a character value.
select lstnam, hex(lstnam) from qiws.qcustcdt LSTNAM HEX ( LSTNAM ) ======== ================ Henning C885959589958740 Jones D1969585A2404040 Vine E589958540404040 Johnson D1968895A2969540 Tyron E3A8999695404040 Stevens E2A385A58595A240 Alison C19389A296954040 Doe C496854040404040 Thomas E388969481A24040 Williams E6899393898194A2 Lee D385854040404040 Abraham C182998188819440
This isn’t terrible, as the last name field is only eight bytes long. In my application, I was dealing with a 40-byte character field, which yielded 80 hexadecimal digits.
Here’s the same output using the LegibleHex function:
select lstnam, legiblehex(trim(lstnam)) from qiws.qcustcdt LSTNAM LEGIBLEHEX ======== ======================== Henning C8 85 95 95 89 95 87 Jones D1 96 95 85 A2 Vine E5 89 95 85 Johnson D1 96 88 95 A2 96 95 Tyron E3 A8 99 96 95 Stevens E2 A3 85 A5 85 95 A2 Alison C1 93 89 A2 96 95 Doe C4 96 85 Thomas E3 88 96 94 81 A2 Williams E6 89 93 93 89 81 94 A2 Lee D3 85 85 Abraham C1 82 99 81 88 81 94
That’s quite an improvement. Now I can tell where one byte begins and another ends. I further improved legibility by chopping off the trailing blanks.
If you would like to use this function, have at it. Here’s the source code, written in my newest favorite language, SQL PL.
create or replace function LegibleHex (p_Value varchar(4096)) returns varchar(12288) deterministic returns null on null input not fenced begin declare v_Length integer; declare v_Index integer; declare v_Work varchar(8192); declare v_Output varchar(12288) default ''; set v_Work = hex(p_Value); set v_Length = length(v_Work); set v_Index = 1; while v_Index < v_Length do set v_Output = v_Output concat substr(v_Work, v_Index, 2) concat ' '; set v_Index = v_Index + 2; end while; return v_Output; end;
Paste the source code into the source physical file member or stream file of your choice. Use the Change Current Library (CHGCURLIB) command to designate the library in which you want the function to reside. Then use the Run SQL Statements (RUNSQLSTM) command to execute the CREATE FUNCTION command. If you’re not sure how to do that, click here.
A proverb of disputed origin says that it is better to light a candle than to curse the darkness. I heartily concur. Consider the LegibleHex function a lit candle.
Hi Ted, another interesting article as usual. Regarding the CHGCURLIB, I’ve been putting some CL commands directly in my SQL so I don’t have to remember to do things manually. For this one, I put a line above the create function statement: CL: CHGCURLIB mylib;
Yes, it’s hard-coding but there are benefits. Thanks for all the great tips.