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



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

我应该得到这个:

结果 1

但我得到这个:

结果 2

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

结果 3

我是一个处理字节和字节数组的新手,所以我不知道我是否必须保存从解码算法中获得的每个结果,或者如果我必须保存字节数组中的每个字节,然后在完成后对其进行解码。如果尝试最后一个选项,我会收到"溢出"错误,而这部分没有更多上下文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'nx10x13rPGx13wRGRxff$x10x0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0exffx04wRGRx8
9x15x15x15x15@xffx04wRGRx88x16x15x16x1axffx04wRGRx88x17x15x17x1cxffx04wRGRx89x18x15x18x15@xffx04wRGRx88x19x15x19x1axffx04wRGRx88x1ax15x1ax1axffx04
wRGRx88x1bx16x15x17xffx04wRGRx88x1cx16x16x16xffx04wRGRx88x1dx16x17x17xffx04wRGRx89x15Aax81pxffx04wRGRx89x15Qax91Pxffx04wRGRx89x15aaxa1Pxffx04wRGRx89x
15qqQ`xffx04wRGRx89x15x81qapxffx04wRGRx89x15x91qq`xffx04wRGRx89x15xa1qx81pxffx04wRGRx89x15xb1qx91pxffx04wRGRx89x15xc1qxa1`xffx04wRGRx89x15xd1x81QPxffx0
4wRGRx89x16Ax91Q`xffx04wRGRx89x16Qxa1QPxffx04wRGRx8ax16axb1QTxffx04wRGRx89x16qxb1ax90xffx03V]Wxff$x10x0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0
ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex0ex10xffx07x10x13gZG_Vxfftr:x02:IG@x02Vxfftr:x01:IG@x01Vxfftr:x00:IG@x00Vxfftr:x07:IG@x07Vxff
tr:x06:IG@x06Vxffx07r:x05:IG@x84vxd4x01Vxffx07r:x04:IG@x84vxd5x01Vxffx01Mxff'

似乎问题在于您错过了将C++continue语句转换为 Python。

替换注释掉的行

#pass

continue

因为 Python 也有一个continue语句,你的代码应该可以工作。

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

代码似乎正在对传入的数据进行某种解压缩/解码,它可以在两种模式下运行:

  • "异或"模式,其中输入中的字符在附加到输出之前先用0x33进行异或处理,
  • "解压缩"模式,从cryptoArray中读取字符,假定包含 16 个常规出现的字符。每个字节的前四位和后四位是对应于要输出的字符的cryptoArray索引。

解码首先通过读取一个字节进行,该字节告诉它使用哪种模式以及在该模式下读取多少字节。 此字节的顶部位明确使用 XOR 模式并设置为使用解压缩模式,其余 7 位给出在该模式下要读取的字节数。 特殊字符xff指示应改为输出换行符。

您的源数据以nx10x13rPGx13wRGR开头,这表示在 XOR 模式下读取 10 个字节(n是字符 10)。 将 10 个字节x10x13rPGx13wRGR0x33进行 XOR 运算会得到文本# Act Data

稍后在数据中,有序列x89x15x15x15x15@. 这表示在解压缩模式下读取 9 个字符,索引 1、5、1、5、1、5 和 4 在cryptoArray中。 (@是字符x40。 这对应于输出中的1 1 1 10,因此我们可以由此推断出cryptoArray索引 1、5 和 4 处的字符分别是空格、10

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

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

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

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

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

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

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

相关内容

最新更新