将 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
마그넬 섬#
マグネル島#
我正在尝试将 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
마그넬 섬#
マグネル島#