10

I have several hex-values that I try to write to a file. It seems that Lua doesn't support that out of the box, since they are all treated as strings instead of values. I figured I would have to break up a longer hex-value, for example AABBCC into AA, BB, CC and use string.char() on all of their decimal values consecutively to get the job done.

Is there a built in function that allows me to write such values directly without converting them first? I used escape characters such as "0xAA" and "\xAA", but those didn't work out.

Edit: Let me give you an example. I'm looking at a test file in a hex editor:

00000000  00  00  00  00  00  00  ......

And I want to write to it in the following fashion with the string "AABBCC":

00000000  AA  BB  CC  00  00  00  ......

What I get though with the escape characters is:

00000000  41  41  42  42  43  43  AABBCC

3 Answers 3

32

I use the following functions to convert between a hex string and a "raw binary":

function string.fromhex(str)
    return (str:gsub('..', function (cc)
        return string.char(tonumber(cc, 16))
    end))
end

function string.tohex(str)
    return (str:gsub('.', function (c)
        return string.format('%02X', string.byte(c))
    end))
end

They can be used as follows:

("Hello world!"):tohex()               --> 48656C6C6F20776F726C6421
("48656C6C6F20776F726C6421"):fromhex() --> Hello world!
Sign up to request clarification or add additional context in comments.

3 Comments

This solution seems to add the hex value 0c0D (or 13) to some, seemingly random places. It was so close to what i needed.
Well, are you writing this on Windows? If yes, then the problem is in the line breaks. While on Unix/Linux/Mac OS X the newline is represented by single '\n' = 0x0A, on Windows when you type a new line, it embeds two bytes - 0x0D, 0x0A (13 10, CR+LF). This may be why you are seeing 0x0D at random places. Try to see if it is near 0x0A - if this is the case, use conversion tools to convert to Unix style (single '\n').
All i needed to do was open the file in Binary mode ("wb") instead of just writing mode ("w"). That fixed the problem.
2

So you have a string like this:

value = 'AABBCC'

And you want to print it (or turn it into a string) like this?

'101010101011101111001100'

How about this?

function hex2bin(str)
    local map = {
        ['0'] = '0000'
        ['1'] = '0001'
        ['2'] = '0010'
        -- etc. up to 'F'
    }
    return str:gsub('[0-9A-F]', map)
end

Note that it leaves untouched any characters which could not be interpreted as hex.

1 Comment

No, I don't want to convert the hexadecimal data, but I want to write a hexadecimal string as a hexadecimal value instead of a string. Let me enhance my above question.
2

There is so such function because it's that easy to write one.

function writeHex(str,fh)
    for byte in str:gmatch'%x%x' do
        fh:write(string.char(tonumber(byte,16)))
    end
end

This just plainly writes the values to the file pointed to by the fh filehandle.

5 Comments

It doesn't work for hex-values that are stored as strings. Which format does "str" need to be for this to work properly?
Well, yeah, you're right, I made a mistake in the code. Fixed it.
I think you mean str:gmatch'%x%x' since %X is the negation of what you're looking for.
Absolutely right. If you have enough reputation, you can directly edit posts to fix such blunders ;). I'll correct it this time, thanks for reporting.
for small numbers it will omit leading zeroes

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.