Ruby 如何在字节数组中找到未知模式?
我正在构建一个工具来帮助我对数据库文件进行反向工程。我将我的工具定位于固定记录长度的平面文件 据我所知: 1) 每个记录都有一个索引(ID)。 2) 每个记录由分隔符分隔。 3) 每条记录都是固定宽度的。 4) 每条记录中的每一列至少由一个x00字节分隔。 5) 文件头位于开头(我这样说是因为头不包含分隔符..) 我在其他文件中找到的分隔符是:(xFAxFA、xFExFE、xFDxFD),但考虑到我将来可能在不同的数据库上使用该工具,这有点无关紧要。因此,我需要一些能够识别“模式”的东西,不管它由多少字节组成。可能不超过6个字节?如果数据量更大,它可能会消耗太多数据。但是,我这样做的经验是有限的 所以我想我的问题是,如何在一个大文件中找到未知的分隔符?我觉得如果“我知道的”我应该能够编程一些东西,我只是不知道从哪里开始Ruby 如何在字节数组中找到未知模式?,ruby,database,reverse-engineering,Ruby,Database,Reverse Engineering,我正在构建一个工具来帮助我对数据库文件进行反向工程。我将我的工具定位于固定记录长度的平面文件 据我所知: 1) 每个记录都有一个索引(ID)。 2) 每个记录由分隔符分隔。 3) 每条记录都是固定宽度的。 4) 每条记录中的每一列至少由一个x00字节分隔。 5) 文件头位于开头(我这样说是因为头不包含分隔符..) 我在其他文件中找到的分隔符是:(xFAxFA、xFExFE、xFDxFD),但考虑到我将来可能在不同的数据库上使用该工具,这有点无关紧要。因此,我需要一些能够识别“模式”的东西,不管它
# Really loose pseudo code
def begin_some_how
# THIS IS THE PART I NEED HELP WITH...
# find all non-zero non-ascii sets of 2 or more bytes that repeat more than twice.
end
def check_possible_record_lengths
possible_delimiter = begin_some_how
# test if any of the above are always the same number of bytes apart from each other(except one instance, the header...)
possible_records = file.split(possible_delimiter)
rec_length_count = possible_records.map{ |record| record.length}.uniq.count
if rec_length_count == 2 # The header will most likely not be the same size.
puts "Success! We found the fixed record delimiter: #{possible_delimiter}
else
puts "Wrong delimiter found"
end
end
可能=[”,“,”]
结果=[0,“]
可能。每个do |分隔符|
size=file.split(分隔符).map{| record | record.size}
下一步,如果size.size<2
平均值=0.0+大小。注入{|和,x |和+x}
average/=size.size#如果这是正确的分隔符,则应为记录长度
偏差=0.0+大小。注入{|和,x |和+(x-平均)**2}
匹配_值=平均/(偏差**2)
如果匹配_值>结果[0],则
结果[0]=匹配的_值
结果[1]=分隔符
结束
结束
利用记录具有恒定大小这一事实。使用每个可能的分隔符,检查每条记录与通常记录长度的偏差。如果与文件的其他部分相比,标题足够小,则应该可以使用。这看起来不错,但我更想问的是如何找到未知模式?我不想定义可能的分隔符,因为它们可以是任意一组随机字节。@Peter Black这就是为什么您必须测试所有可能的分隔符。这样想:如果是你在看文件而不是你的计算机,你怎么猜什么是分隔符,什么不是?尝试一些,看看哪些行为像一个分隔符。所以,唯一的方法是通过寻找未知的模式?我有点希望有某种算法可以测试模式。例如:1)查找所有重复两次以上的2个或更多字节的非零非ascii集。2) 测试上述任何一项是否总是彼此间隔相同的字节数(除了一个实例,头…)。
possible = [",", "."]
result = [0, ""]
possible.each do |delimiter|
sizes = file.split( delimiter ).map{ |record| record.size }
next if sizes.size < 2
average = 0.0 + sizes.inject{|sum,x| sum + x }
average /= sizes.size #This should be the record length if this is the right delimiter
deviation = 0.0 + sizes.inject{|sum,x| sum + (x-average)**2 }
matching_value = average / (deviation**2)
if matching_value > result[0] then
result[0] = matching_value
result[1] = delimiter
end
end