我必须编写一个程序来解码文件(使用CP437编码),方法是根据CP437表替换每个符号的Unicode,然后将其转换为UTF-8并将输出打印到文件中。
我有两个文件-一个输入文件,其中包含一个长文本,同时包含正常字符和一些奇怪的字符(在结果文件中,这些奇怪的字符将由各种破折号代替),以及一个CP437文件,其中包含256行对(第一部分是十进制数字,第二部分是Unicode,例如73 0049)。
这就是我试图解决此问题的方法:
此外,如果UTF-8 0和1s的长度大于8,则我每8个字符将其分割一次,然后将其转换为字节(我不确定这是否正确)
主要问题是,当我尝试编写结果时,出现很多乱码,并且不确定问题出在哪里。非常感谢您的帮助,我已经被这项工作困扰了一段时间,只是无法找出问题所在。
def convertBinToHex(binary):
binToHex = hex(int(binary, 2))
temp = list(binToHex)
temp = temp[2:]
binToHex = "".join(temp).upper()
return binToHex
def convertUnicodeToUTF(unicodeBin, symbolDecimal, returnBin):
# https://stackoverflow.com/questions/6240055/manually-converting-unicode-codepoints-into-utf-8-and-utf-16
bytesCount = 0
if int("0000", 16) <= symbolDecimal <= int("007F", 16):
if returnBin:
return unicodeBin
return convertBinToHex(unicodeBin)
elif int("0080", 16) <= symbolDecimal <= int("07FF", 16):
bytesCount = 2
elif int("0800", 16) <= symbolDecimal <= int("FFFF", 16):
bytesCount = 3
elif int("10000", 16) <= symbolDecimal <= int("10FFFF", 16):
bytesCount = 4
else:
return
if bytesCount == 2:
template = ['1', '1', '0', 'x', 'x', 'x', 'x', 'x', '1', '0', 'x', 'x', 'x', 'x', 'x', 'x']
elif bytesCount == 3:
template = ['1', '1', '1', '0', 'x', 'x', 'x', 'x', '1', '0', 'x', 'x', 'x', 'x', 'x', 'x', '1', '0', 'x', 'x',
'x',
'x', 'x', 'x']
elif bytesCount == 4:
template = ['1', '1', '1', '1', '0', 'x', 'x', 'x', '1', '0', 'x', 'x', 'x', 'x', 'x', 'x', '1', '0', 'x', 'x',
'x',
'x', 'x', 'x', '1', '0', 'x', 'x', 'x', 'x', 'x', 'x']
else:
return
results = []
unicodeList = list(unicodeBin)
counter = len(unicodeList) - 1
for el in reversed(template):
if el == 'x':
if counter >= 0:
results.append(unicodeList[counter])
counter -= 1
else:
results.append('0')
elif el == '0':
results.append('0')
else:
results.append('1')
results.reverse()
results = "".join(results)
if returnBin:
return results
else:
return convertBinToHex(results)
codePage = {}
with open("CP437.txt") as f:
for line in f:
(key, val) = line.split()
codePage[key] = val
text = []
with open("386intel.txt", 'rb') as f:
while True:
c = f.read(1)
if c:
# Converts bytes to bits (string)
text.append("{:08b}".format(int(c.hex(), 16)))
if not c:
print("End of file")
break
bytesString = 0
bytesStringInt = 0
resultFile = open("rez.txt", "wb")
for item in text:
decimalValue = int(item, 2)
newUnicode = codePage[str(decimalValue)]
unicodeToBin = "{0:08b}".format(int(newUnicode, 16))
bytesString = convertUnicodeToUTF(unicodeToBin, decimalValue, True)
if len(bytesString) > 8:
bytesStringSplit = [bytesString[i:i + 8] for i in range(0, len(bytesString), 8)]
for x in bytesStringSplit:
bytesStringInt = int(x, 2)
resultFile.write(bytes([bytesStringInt]))
# print(bytes([bytesStringInt]))
else:
bytesStringInt = int(bytesString, 2)
resultFile.write(bytes([bytesStringInt]))
# print(bytes([bytesStringInt]))
答案 0 :(得分:0)
未经测试,因为您忽略了提供输入文件:
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
my @cp;
{
open my $fh, '<', 'CP437.txt';
while (my $line = readline $fh) {
chomp $line;
my ($k, $v) = split ' ', $line;
$cp[$k] = chr hex $v;
}
}
{
open my $in, '<:raw', '386intel.txt';
open my $out, '>:encoding(UTF-8)', '386intel.txt.utf8';
while (my $line = readline $in) {
$out->print(
join '', # 5. join characters into string
map { # 2. loop over octets
$cp[ # 4. look up character corresponding to
# octet numeric value
ord # 3. numeric value of octet
]
}
split '', $line # 1. split line into octets
);
}
}
该程序非常容易理解,仅包含10行有效代码(如果需要,还可以轻松移植到Python)。
如果文件CP437.txt符合标准,那么它就变成:
› piconv -f CP437 -t UTF-8 < 386intel.txt > 386intel.txt.utf8
如果分配确实涉及对UTF-8进行手动编码而不是使用库,则在代码中chr
所在的位置进行替换。