Конвертировать Ruby Script в Python - Проблема с кодированием / декодированием байтов - PullRequest
0 голосов
/ 28 октября 2018

Я пытаюсь преобразовать скрипт ruby ​​в скрипт python.Сценарий должен читать двоичный файл и преобразовывать его в читаемые строки.Бинарный файл содержит некоторые корейские символы.Я пробовал многократное декодирование, но ни одно из них не помогло.В конце данные должны быть отформатированы в таблицу.(Не видно в этом коде, только что упомянуто для лучшего понимания)

Скрипт ruby ​​работает без проблем вообще.

Я не уверен, нужен ли тестовый файл, но я загрузил его на Mediafire .

Спасибо за помощь!:)

Ruby Script:

# 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 Script

# 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()

1 Ответ

0 голосов
/ 28 октября 2018

Я думаю, что основная проблема заключается в том, что вы помещаете косые черты, которые используются в качестве разделителя регулярного выражения в 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
마그넬 섬#
マグネル島#
...