将 Ruby 脚本转换为 Python - encoding/decoding 字节的问题

Convert Ruby Script to Python - Problem with encoding/decoding of bytes

我正在尝试将 ruby 脚本转换为 python 脚本。该脚本应该读取二进制文件并将其转换为可读字符串。二进制文件包含一些韩语符号。我尝试了多次解码,但 none 似乎有效。最后,数据应该被格式化为table。 (在这段代码中没有看到,只是为了更好地理解而提到的)

ruby 脚本运行良好,没有任何问题。

我不确定是否需要测试文件,但我已经上传了它on Mediafire

感谢您帮助我! :)

Ruby 脚本:

# encoding: utf-8

def columntypes(t)
    case(t)
      when 0
        return 4
      when 1
        return 4
      when 2
        return 4
      when 3
        return 12
      when 4
        return 32
      when 5
        return 128
    end
    return 0
end

  doc = File.open("test.bin", "rb")

  bin = {
    'datasets'=>doc.read(4).unpack("l*")[0],
    'datasetslength'=>doc.read(4).unpack("l*")[0],
    'columns'=>doc.read(4).unpack("l*")[0]
  }

  columns = Array.new
  bin['columns'].times do |i|
    columns << {'name'=>doc.read(32).gsub(/\x00.*/, "").encode('utf-8', 'EUC-KR').strip, 'length'=>columntypes(doc.read(4).unpack("l*")[0])}
  end

  datasets = Array.new
  bin['datasets'].times do |d|
    trash = doc.read(4)
    dataset = Array.new
    columns.each do |c|
      data = doc.read(c['length'])
      puts "#{data}"
      if c['length']!=4 then
        #string
        dataset << data.gsub(/\x00.*/, "").encode('utf-8', 'EUC-KR').chomp
      else
        #float/integer
        dataset << data.unpack("L")[0]
      end
    end
    datasets << dataset
  end
end

Python 脚本

# encoding: utf-8
import struct
import re

def columntypes(t):
    if t == 0:
        return 4
    elif t == 1:
        return 4
    elif t == 2:
        return 4
    elif t == 3:
        return 12
    elif t == 4:
        return 32
    elif t == 5:
        return 128
    else:
        return 0

doc = open("test.bin", "rb")

b = {
    "datasets": struct.unpack("l", doc.read(4))[0],
    "datasets_length": struct.unpack("l", doc.read(4))[0],
    "columns": struct.unpack("l", doc.read(4))[0],
}

columns = []
for x in range(b["columns"]):
    data = doc.read(32)
    data = re.sub(b"/\x00.*/", b"", data)
    data = data.decode("utf-8")
    name = data.rstrip("\x00")

    columns.append(
        {
            "name": name,
            "length": columntypes(struct.unpack("l", doc.read(4))[0])
        }
    )

datasets = []
for x in range(b["datasets"]):
    trash = doc.read(4)
    dataset = []
    for c in columns:
        data = doc.read(c["length"])

        if c["length"] != 4:
            data = re.sub(b"/\x00.*/", b"", data)
            # Error here
            # Encodings tried: utf-8, euc_kr, cp949
            d = data.decode("utf-8").rstrip("\x00")

            datasets.append(d)

        else:
            datasets.append(struct.unpack("L", data)[0])

doc.close()

我认为主要问题是您将 ruby 中用作正则表达式分隔符的斜线也放在了 python 字符串中,这会破坏替换。 变化

         data = re.sub(b"/\x00.*/", b"", data)

         data = re.sub(b"\x00.*", b"", data)

而且应该会更好。

我还需要在各种解包调用中将 "l" 替换为 "i",我不确定这是否正常,但这对我有用。

来自 "d"

的示例输出
ISLAND_00
카디프섬#
カ?ディフ島#
Cardiff Island#
Cardiff Island#
Cardiff Island#
Cardiff Island#
Cardiff Island#
Cardiff Island#
Cardiff Island#
?迪夫?#
?迪夫島#
ISLAND_01
마그넬 섬#
マグネル島#