'charmap' 编解码器无法对位置 0 中的字符 '\x92' 进行编码:字符映射到 <undefined>

'charmap' codec can't encode character '\x92' in position 0: character maps to <undefined>

我正在尝试使用 Qt 库(python 中的 Pyside2)将一些函数从 C++ 传递到 Python。目前一切正常,将代码从一侧传递到另一侧并使其适应 Python,但是当我开始处理某些文件“翻译”时,我得到了不同的结果,有时还出现错误。

我应该得到这个:

Result 1

但我得到的是这个:

Result 2

或者我将每个字节附加到数组 chr() 我得到这个:

Result 3

我是处理字节和字节数组的新手,所以我不知道我是否必须保存从算法解码得到的每个结果,或者我是否必须保存字节数组中的每个字节然后对其进行解码当它完成时。如果尝试最后一个选项,我会在这部分没有更多上下文的情况下收到“OverFlow”错误 decryptedFile.append(currentByte ^ 0x33)

我想修复此代码以使其正常工作。谢谢大家!

这是C++中的原始函数:

QByteArray NosTextDatFileDecryptor::decrypt(QByteArray &array) {
    QByteArray decryptedFile;
    int currIndex = 0;
    while (currIndex < array.size()) {
        unsigned char currentByte = array.at(currIndex);
        currIndex++;
        if (currentByte == 0xFF) {
            decryptedFile.push_back(0xD);
            continue;
        }
        int validate = currentByte & 0x7F;
        if (currentByte & 0x80) {
            for (; validate > 0; validate -= 2) {
                if (currIndex >= array.size())
                    break;
                currentByte = array.at(currIndex);
                currIndex++;
                int firstByte = cryptoArray.at((currentByte & 0xF0) >> 4);
                decryptedFile.push_back(firstByte);
                if (validate <= 1)
                    break;
                int secondByte = cryptoArray.at(currentByte & 0xF);
                if (!secondByte)
                    break;
                decryptedFile.push_back(secondByte);
            }
        } else {
            for (; validate > 0; --validate) {
                if (currIndex >= array.size())
                    break;
                currentByte = array.at(currIndex);
                currIndex++;
                decryptedFile.push_back(currentByte ^ 0x33);
            }
        }
    }
    return decryptedFile;
}

这是我的项目 Python 版本的代码:

from PySide2.QtCore import QByteArray

def dat_file_decryptor(array):
    decryptedFile = QByteArray()
    currIndex = 0
    while currIndex < array.size():
        currentByte = ord(array[currIndex]) #unsigned char
        currIndex += 1
        if currentByte == 0xFF:
            decryptedFile.append(0xD)
            #pass
        validate = currentByte & 0x7F
        if currentByte & 0x80:
            while validate > 0:
                if currIndex >= array.size():
                    break
                currentByte = ord(array[currIndex])
                currIndex += 1
                firstByte = cryptoArray[(currentByte & 0xF0) >> 4]
                decryptedFile.append(firstByte)
                if validate <= 1:
                    break
                secondByte = cryptoArray[currentByte & 0xF]
                if not secondByte:
                    break
                decryptedFile.append(secondByte)
                validate -= 2
        else:
            while validate > 0:
                if currIndex >= array.size():
                    break
                currentByte = ord(array[currIndex])
                currIndex +=1
                decryptedFile.append(chr(currentByte ^ 0x33)) #If I don't use chr() here I get an OverFlow error
                validate -= 1
    return decryptedFile

如果您想自己尝试,这是您需要的数据:

array = b'\n\x10\x13rPG\x13wRGR\xff$\x10\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\xff\x04wRGR\x8
9\x15\x15\x15\x15@\xff\x04wRGR\x88\x16\x15\x16\x1a\xff\x04wRGR\x88\x17\x15\x17\x1c\xff\x04wRGR\x89\x18\x15\x18\x15@\xff\x04wRGR\x88\x19\x15\x19\x1a\xff\x04wRGR\x88\x1a\x15\x1a\x1a\xff\x04
wRGR\x88\x1b\x16\x15\x17\xff\x04wRGR\x88\x1c\x16\x16\x16\xff\x04wRGR\x88\x1d\x16\x17\x17\xff\x04wRGR\x89\x15Aa\x81p\xff\x04wRGR\x89\x15Qa\x91P\xff\x04wRGR\x89\x15aa\xa1P\xff\x04wRGR\x89\x
15qqQ`\xff\x04wRGR\x89\x15\x81qap\xff\x04wRGR\x89\x15\x91qq`\xff\x04wRGR\x89\x15\xa1q\x81p\xff\x04wRGR\x89\x15\xb1q\x91p\xff\x04wRGR\x89\x15\xc1q\xa1`\xff\x04wRGR\x89\x15\xd1\x81QP\xff\x0
4wRGR\x89\x16A\x91Q`\xff\x04wRGR\x89\x16Q\xa1QP\xff\x04wRGR\x8a\x16a\xb1QT\xff\x04wRGR\x89\x16q\xb1a\x90\xff\x03V]W\xff$\x10\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0
e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x10\xff\x07\x10\x13gZG_V\xff\tr:\x02:IG@\x02V\xff\tr:\x01:IG@\x01V\xff\tr:\x00:IG@\x00V\xff\tr:\x07:IG@\x07V\xff\
tr:\x06:IG@\x06V\xff\x07r:\x05:IG@\x84v\xd4\x01V\xff\x07r:\x04:IG@\x84v\xd5\x01V\xff\x01M\xff'

看来问题是您错过了将 C++ continue 语句转换为 Python.

替换注释掉的行

            #pass

            continue

as Python also has a continue statement,你的代码应该可以工作。

在循环中,continue 语句导致循环当前迭代的其余部分结束,并从下一次迭代继续执行。

似乎代码正在对传入数据执行某种 decompression/decoding,并且它可以在两种模式下运行:

  • 'XOR' 模式,其中输入的字符在附加到输出之前是 XOR-ed 和 0x33
  • 'Decompression'模式,其中字符从cryptoArray读取,假定包含16个regularly-appearing字符。每个字节的前四位和后四位是 cryptoArray 的索引,对应于要输出的字符。

解码首先通过读取一个字节来进行,该字节告诉它使用哪种模式以及在该模式下要读取多少字节。该字节的最高位明确使用异或模式并设置为使用解压缩模式,其余七位给出该模式下要读取的字节数。特殊字符 \xff 表示应该输出一个换行符。

您的源数据以 \n\x10\x13rPG\x13wRGR 开头,这表示以 XOR 模式读取 10 个字节(\n 是字符 10)。将 10 个字节 \x10\x13rPG\x13wRGR0x33 异或得到文本 # Act Data.

稍后在您的数据中,有序列 \x89\x15\x15\x15\x15@。这表示在解压模式下读取 9 个字符,在 cryptoArray 中的索引 1, 5, 1, 5, 1, 5, 1, 5 和 4 处。 (@ 是字符 \x40。)这对应于输出中的 1 1 1 10,因此我们可以推断出 cryptoArray 中索引 1、5 和 4 处的字符是space、10

你没有在你的问题中指定 cryptoArray 的内容,但以下似乎为我产生了正确的输出:

#                          0123456789abcdef
cryptoArray = QByteArray(b'X XX0123456789XX')

Xs 表示未在此特定转换中使用的字节,因此我无法说明它们在您的代码中是什么。

那么为什么您的代码生成了不正确的输出?缺少的continue语句在\xff字节的处理中,表示输出换行符。如果没有 continue 语句,代码将输出换行符,然后在解压缩模式下错误地尝试从数据的下一个 64 字节中解码 127 个字符。

无论如何,你的函数 dat_file_decryptor returns 一个 QByteArray。我将它分配给一个变量 result,我可以通过 运行 以下行从您的源数据中获得所需的输出:

print(bytes(result).decode("ascii").replace("\r", "\n"))

免责声明:我没有在 PySide 中测试过这个,只有 PyQt5。我不知道这是否有所作为。