需要帮助将Python命令转换为Lua。

huangapple go评论48阅读模式
英文:

Need help in converting the python command into lua

问题

以下是你要翻译的部分:

I need help in converting the below python commands which are basically extracting the CRC of a file (*.LUH or *.bin) file into Lua commands.

filename_expected = os.path.abspath(header_path)

# Read and extract data from Header.LUH

f = open(filename_expected, 'rb')
header_data = f.read()
f.close()

# Create a list of Python integers representing header_bytes in file

header_bytes = map(ord, header_data)
partnum_len = header_bytes[27]

# Convert ordinals to a list of string'ized two-digit hex numbers e.g. ['0a', '02', '34', 'ff', 'e7', ...]

bytes_in_hex_representation = map(lambda n: "%.2x" % n, header_bytes)

# Get hex representation of desired header_bytes

header_crc_number = ''.join(bytes_in_hex_representation[-4:])

我已将这段Python代码翻译为Lua代码,以下是Lua版本的代码:

-- 我需要帮助将以下Python命令转换为Lua命令,基本上是提取文件(*.LUH或*.bin)的CRC。

filename_expected = os.path.abspath(header_path)

-- 从Header.LUH中读取并提取数据

f = io.open(filename_expected, 'rb')
header_data = f:read("*a")
f:close()

-- 创建一个表示文件中header_bytes的Python整数列表

header_bytes = {}
for i = 1, #header_data do
    table.insert(header_bytes, string.byte(header_data, i))
end
partnum_len = header_bytes[28]  -- Lua中索引从1开始

-- 将ordinals转换为一个由两位十六进制数字字符串组成的列表,例如['0a', '02', '34', 'ff', 'e7', ...]

bytes_in_hex_representation = {}
for i = 1, #header_bytes do
    table.insert(bytes_in_hex_representation, string.format("%02x", header_bytes[i]))
end

-- 获取所需header_bytes的十六进制表示

header_crc_number = table.concat(bytes_in_hex_representation, "", #bytes_in_hex_representation - 3, #bytes_in_hex_representation)

请注意,在Lua中,索引是从1开始的,所以我相应地调整了代码中的索引。 Lua没有像Python中的mapordlambda这些特定函数,因此我使用了适当的Lua函数来实现相同的功能。

英文:

I need help in converting the below python commands which are basically extracting the CRC of a file(*.LUH or *.bin) file into Lua commands.

filename_expected = os.path.abspath(header_path)

Read and extract data from Header.LUH

f = open(filename_expected, 'rb')
header_data = f.read()
f.close()

Create a list of Python integers representing header_bytes in file

header_bytes = map(ord, header_data)
partnum_len = header_bytes\[27\]

Convert ordinals to a list of string'ized two-digit hex numbers e.g. ['0a', '02', '34', 'ff', 'e7', ...]

bytes_in_hex_representation = map(lambda n: "%.2x" % n, header_bytes)

Get hex representation of desired header_bytes

header_crc_number = ''.join(bytes_in_hex_representation[-4:])

I have started to write that into lua, came only this till reading the data.

header_file = 'header.LUH'
header_path = ".\\table\\" .. header_file

\-- Read and extract data from Header.LUH
file = io.open(header_path, 'r')
t = file:read("\*all")
print(t)
file:close()

Does Lua has any commands like 'map'or 'ord' or lambda ??

答案1

得分: 1

Lua 不需要 lambda,因为 Lua 中的函数都是匿名的(也就是说,它们是值)。

Lua 很简洁,它没有 map,但你可以自己实现它。相当于 ord 的函数是 string.byte

无论如何,让我们分解它:

设置路径:

local header_path = [[.\table\header.LUH]]

我在这里使用了一个本地变量和一个“长字符串文字”。你的代码也是可以的。

打开文件:

local file = io.open(header_path, "rb")

注意,在 Lua 中对于二进制文件,你需要使用 "rb",就像在 Python 或其他合理的语言中一样;你不能只使用 "r" - 否则 Windows 系统会执行换行标准化,使你读取 CRLF 字节而不是 LF(例如,PNG 头部包含 LF 以检查此问题)。

读取整个内容:

local content = file:read"*a"

较新的 Lua 版本也接受只使用 "a"。你不能转义星号 - 这样做会引发语法错误("无效的转义序列")。

使用 file:close() 关闭文件是可以的 - 但是,如果发生错误,你可能不会关闭文件。在 Lua 5.4 中,你可以将 file 标记为将要关闭的变量,使用 <close> 来使它在超出作用域时自动关闭(成功或通过错误):local file <close> = io.open(header_path, "rb")

在 Python 中,你现在将字节转换为整数列表。在 Lua 中,你不需要这一额外步骤。你可以直接将字符串视为字节字符串,并使用 string.gsub 将字节转换为十六进制对:

local content_hex = content:gsub(".", function(char) return ("%02x"):format(char:byte()) end)

这里使用 char:byte() 将字符转换为其数值表示,并使用 string.format 将该数字格式化为一个两位十六进制字符串。

然后,你可以使用 string.sub 提取所需的十六进制数字(最后 4 位,相当于最后 2 个字节):

local crc_hex = content_hex:sub(-4)

然后你完成了!然而,这段代码进行了大量额外的工作;它将整个文件读入内存并将其转换为十六进制,只为了在最后进行 CRC 校验。相反,你应该在文件末尾前查找 2 个字节,读取这两个字节,然后按上述方式将它们转换为十六进制:

file:seek("end", -2)
local crc = file:read(2)
local crc_hex = content:gsub(".", function(char) return ("%02x"):format(char:byte()) end)

这将更加高效(要求远远少于磁盘 I/O),需要更少的内存(只有 2 个字节被读入内存)和更少的 CPU 时间(只有 2 个字节被转换为十六进制)。总体而言,你将从线性时间复杂度变为常数时间复杂度!

英文:

Lua does not need lambda since functions in Lua are all anonymous (that is, they are values).

Lua is minimalistic; it does not have map, but you can implement it yourself. The equivalent to ord is string.byte.

Anyways, let's break it down:

Setting the path:

local header_path = [[.\table\header.LUH]]

I've used a local variable and a "long string literal" here. Your code is fine too.

Opening the file:

local file = io.open(header_path, &quot;rb&quot;)

Note that you need rb in Lua for binary files (just like in Python or any other sane language); you may not use just r - otherwise Windows systems will perform line feed normalization, making you read the CRLF bytes instead of LF (the PNG header for instance contains LF to check against this).

For reading the entire contents:

local content = file:read&quot;*a&quot;

newer Lua versions will also accept just a. You may not escape the asterisk - doing so should throw a syntax error ("invalid escape sequence").

Closing the file using file:close() is fine - however, if an error happens in-between, you may end up not closing the file. In Lua 5.4, you could mark file as a to-be-closed variable using &lt;close&gt; to have it be closed automatically as it goes out of scope (successfully or through error): local file &lt;close&gt; = io.open(header_path, &quot;rb&quot;).

In Python, you're now converting the bytes to a list of integers. In Lua, you wouldn't take this extra step. You'd directly treat the string as a bytestring and convert bytes to hex pairs using string.gsub:

local content_hex = content:gsub(&quot;.&quot;, function(char) return (&quot;%02x&quot;):format(char:byte()) end)

This uses char:byte() to convert the character to its numeric representation and string.format to format this number as a two-digit hex string.

You can then substring the desired hex digits (the last 4 digits, equivalent to the last 2 bytes) using string.sub:

local crc_hex = content_hex:sub(-4)

and you're done! However, this code does plenty of extra work; it reads the entire file into memory and converts it into hex just for the CRC checksum at the end. You should instead seek 2 bytes before the end, read the two bytes, then convert them to hex as described above:

file:seek(&quot;end&quot;, -2)
local crc = file:read(2)
local crc_hex = content:gsub(&quot;.&quot;, function(char) return (&quot;%02x&quot;):format(char:byte()) end)

This will be vastly more efficient (much, much less disk I/O), will require much less memory (only 2 bytes are read into memory) and much less CPU time (only 2 bytes are converted to hex). Overall, you're looking at going from linear to constant time!

huangapple
  • 本文由 发表于 2023年3月7日 15:50:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75659230.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定