解码使用CP437制表符编码的文件

2024-10-01 09:28:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我必须编写一个程序来解码一个文件(使用CP437编码),根据CP437表替换每个符号的Unicode,然后将其转换为UTF-8并将输出打印到一个文件中。你知道吗

我有两个文件-一个输入文件包含一个长文本,其中包含普通字符和一些奇怪的字符(在结果文件中,这些奇怪的字符将被各种破折号替换),一个CP437文件包含256行对(第一部分是十进制数,第二部分是Unicode,例如73 0049)。你知道吗

这就是我试图解决这个问题的方法:

  1. 使用“RB”标志打开输入文件
  2. 因为我是用“RB”打开文件的,所以我把每个符号都读作字节,然后把它存储在“text”列表中
  3. 看完文件后,我循环浏览文本列表
  4. 在循环过程中,我得到符号的十进制值
  5. 我使用十进制值从CP437.txt文件中获取Unicode
  6. 我将Unicode转换为0和1
  7. 我将Unicode的二进制表示转换为UTF-8和 返回0和1
  8. 我将这些UTF-80和1转换成字节,并将它们写入 使用“WB”标志打开的结果文件

另外,如果UTF-80s和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]))

Tags: 文件inforreturnifunicodeelseresults
1条回答
网友
1楼 · 发布于 2024-10-01 09:28:04

未测试,因为您忽略了提供输入文件:

#!/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函数所在的位置进行替换。你知道吗

相关问题 更多 >