首页 > 解决方案 > 超过一个字节后的lua解析

问题描述

如何在超过一个字节后解析二进制文件?例如:

56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 EF BF BD 00 EF BF BD 1F 56 30 30 31 01 00 00 00 EF BF BD EF BF BD 2A 5C BF BD 03 02 45 24 56 30 30 31 04 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 13 00 00 00 56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5 BD 03 01 45 7E 12 02 24 00 4D EF BF

我想在 0x56 0x30 0x30 0x31 之后解析这个。我怎样才能做到这一点?在每个新的 0x56 0x30 0x30 0x31 之前,旧的数据包(字符串)应该结束。

像这样:

56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 EF BF BD 00 EF BF BD 1F

56 30 30 31 01 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 24

56 30 30 31 04 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 13 00 00 00

56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 24 00 4D EF BF

我已经做了一些类似的事情来解析一个字节到一个表中。但我不能把它变成我的新问题。这就是一个字节0x7E之后的解析代码。

function print_table(tab)
print("Table:") 
for key, value in pairs(tab) do
  io.write(string.format("%02X ", value))  
end
print("\n") 
end

local function read_file(path, callback) 
local file = io.open(path, "rb") 
if not file then 
 return nil
end
local t = {} 
repeat
local str = file:read(4 * 1024)   
for c in (str or ''):gmatch('.') do  
    if c:byte() == 0x7E then 
        callback(t) -- function print_table
        t = {}
    else
        table.insert(t, c:byte())  
    end
end
until not str
file:close() 
return t 
end

local result = {}
function add_to_table_of_tables(t)
table.insert(result, t) 
end

local fileContent = read_file("file.dat", print_table)

重要的是 56 30 30 31 在字符串中首先写入。感谢您的帮助!

我还需要从文件中读取我的输入。我正在阅读这样的文件:

local function read_file(path) --function read_file
  local file = io.open(path, "rb") -- r read mode and b binary mode
  if not file then return nil end
  local content = file:read "*all" -- *all reads the whole file
  file:close()
  return content
end

标签: parsingluahexbyte

解决方案


您可以使用gsub将目标子字符串替换为输入字符串唯一的单个字符,我将\n在此示例中使用。之后,您可以使用gmatch来选择一系列不是替换字符的字符。

local input = [[56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 EF BF BD 00 EF BF BD 1F 56 30 30 31 01 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 24 56 30 30 31 04 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 13 00 00 00 56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 24 00 4D EF BF]]

local pattern ="([^\n]+)"
local rowPrefix = "56 30 30 31"

input = input:gsub(rowPrefix, "\n")

for row in input:gmatch(pattern) do
  print(rowPrefix .. row)
end

输出:

56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 EF BF BD 00 EF BF BD 1F 
56 30 30 31 01 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 24 
56 30 30 31 04 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 13 00 00 00 
56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 24 00 4D EF BF

更多信息的资源:

Lua 编程:20.1 – 模式匹配函数

Lua 5.3 参考手册:string.gmatch

Lua 5.3 参考手册:string.gsub


推荐阅读