Lua:将十六进制值写入二进制文件

9
我有几个十六进制值,想要将它们写入文件。Lua似乎不支持此项功能,因为这些值都被视为字符串而非数值。我想我得将较长的十六进制值(例如AABBCC)分解成AA、BB和CC,并对它们连续使用string.char()以获取所需结果。
是否有内置函数可以直接写入这些值而无需先进行转换?我使用了像"0xAA"和"\xAA"之类的转义字符,但它们没有起作用。
编辑:让我举个例子。我正在查看一个测试文件的十六进制编辑器:
00000000  00  00  00  00  00  00  ......

我希望使用字符串"AABBCC"来按照以下方式写入:

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

我用转义字符得到的结果是:
00000000  41  41  42  42  43  43  AABBCC
3个回答

30

我使用以下函数在十六进制字符串和“原始二进制”之间进行转换:

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

它们可以按以下方式使用:

("Hello world!"):tohex()               --> 48656C6C6F20776F726C6421
("48656C6C6F20776F726C6421"):fromhex() --> Hello world!

这个解决方案似乎在一些看起来随机的位置添加了十六进制值0c0D(或13)。它非常接近我所需要的。 - Delusional Logic
1
你是在Windows上写这个程序吗?如果是的话,问题可能出在换行符上。在Unix/Linux/Mac OS X中,换行符用单个'\n'=0x0A表示,而在Windows中,当你输入一个新行时,它会嵌入两个字节-0x0D、0x0A(13 10, CR+LF)。这可能是为什么你会在随机位置看到0x0D的原因。尝试查看是否靠近0x0A-如果是这种情况,使用转换工具将其转换为Unix样式(单个'\n')。 - Michal Kottman
1
我所需要做的就是以二进制模式("wb")打开文件,而不仅仅是写入模式("w")。这样问题就解决了。 - Delusional Logic

2

所以你有一个像这样的字符串:

value = 'AABBCC'

你想要像这样打印它(或将其转换为字符串)吗?
'101010101011101111001100'

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

请注意,它不会改变任何无法解释为十六进制的字符。

不,我不想转换十六进制数据,而是想将十六进制字符串作为十六进制值写入,而不是字符串。让我改进一下我的问题。 - Zerobinary99

1

没有这样的函数,因为编写一个函数很容易。

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

这只是将值简单地写入由fh文件句柄指向的文件中。


它不能处理存储为字符串的十六进制值。为了使其正常工作,“str”需要采用哪种格式? - Zerobinary99
嗯,没错,我的代码有错误。已经修复了。 - jpjacobs
我认为你的意思是str:gmatch'%x%x',因为%X是你要查找的内容的否定。 - greatwolf
完全正确。如果您有足够的声望,您可以直接编辑帖子来修复这样的错误;)。我会纠正它,感谢您的报告。 - jpjacobs
对于小数字,它将省略前导零。 - socketpair

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接