3

わかりましたので、私の問題は、文字列 '\222\222\223\225' がデータベースに latin-1 として格納されていることです。django から (印刷して) 得られるのは、次の文字列 'ââââ¢' です。次に、この操作を行う関数に文字列を渡す必要があります。

strdecryptedPassword + chr(ord(c) - 3 - intCounter - 30)

次のエラーが表示されます。

chr() arg が範囲外 (256)

最初に文字列を latin-1 としてエンコードしようとすると、次のエラーが発生します。

'latin-1' コーデックは位置 0 ~ 3 の文字をエンコードできません: 序数が範囲外です (256)

文字エンコーディングがどのように機能するかについてたくさん読んだことがありますが、理解できないために欠けているものがあります!

4

3 に答える 3

4

最初のエラー 'chr() arg not in range(256)' は、chr が負の数を取ることができないため、おそらく値がアンダーフローしたことを意味します。inputcounter + 33 が実際の文字表現よりも大きい場合、暗号化アルゴリズムが何をすべきかわかりません。その場合の対処方法を確認する必要があります。

2つ目のエラーについて。データの適切な表現を取得するには、通常の文字列オブジェクトを encode() ではなく、decode() する必要があります。encode() は Unicode オブジェクト (u' で始まるもの) を取り、ファイルに出力または書き込む通常の文字列を生成します。decode() は文字列オブジェクトを受け取り、対応するコード ポイントで Unicode オブジェクトを生成します。これは、文字列オブジェクトから生成されたときに unicode() 呼び出しで行われます。代わりに a.decode('latin-1') を呼び出すこともできます。

>>> a = '\222\222\223\225'
>>> u = unicode(a,'latin-1')
>>> u
u'\x92\x92\x93\x95'
>>> print u.encode('utf-8')
ÂÂÂÂ
>>> print u.encode('utf-16')
ÿþ
>>> print u.encode('latin-1')

>>> for c in u:
...   print chr(ord(c) - 3 - 0 -30)
...
q
q
r
t
>>> for c in u:
...   print chr(ord(c) - 3 -200 -30)
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError: chr() arg not in range(256)
于 2008-11-08T05:29:37.937 に答える
2

Vinkoが指摘しているように、Latin-1またはISO 8859-1には、引用する8進文字列の印刷可能な文字がありません。8859-1に関する私のメモによると、「C1コントロール(0x80-0x9F)はISO / IEC 6429:1992からのものです。80、81、または99の名前は定義されていません」。コードポイント名は、Vinkoがリストしているとおりです。

\222 = 0x92 => PRIVATE USE TWO
\223 = 0x93 => SET TRANSMIT STATE
\225 = 0x95 => MESSAGE WAITING

それらの正しいUTF-8エンコーディングは(Unicode、binary、hex)です:

U+0092 = %11000010 %10010010 = 0xC2 0x92
U+0093 = %11000010 %10010011 = 0xC2 0x93
U+0095 = %11000010 %10010101 = 0xC2 0x95

CIRCUMFLEXを使用したラテン文字Aは、ISO 8859-1コード0xE2であるため、Unicode U+00E2です。UTF-8では、%11000011%10100010または0xC30xA2です。

CENTSIGNはISO8859-1コード0xA2であるため、Unicode U+00A2です。UTF-8では、%11000011%10000010または0xC30x82です。

したがって、他に表示されているものが何であれ、ISO8859-1のUTF-8エンコーディングは表示されていないようです。他のすべてを除いて、あなたはあなたが見ているのは5バイトですが、あなたは8を見る必要があります。

追加:回答の前の部分は「UTF-8エンコーディング」の主張に対応していますが、質問の残りの部分は無視しています。

Now I need to pass the string into a function that does this operation:

    strdecryptedPassword + chr(ord(c) - 3 - intCounter - 30)

I get this error: chr() arg not in range(256).  If I try to encode the
string as Latin-1 first I get this error: 'latin-1' codec can't encode
characters in position 0-3: ordinal not in range(256).

intCounterがどのように定義されているかを実際に示すことはありませんが、文字ごとに緩やかに増加する場合、遅かれ早かれ' ord(c) - 3 - intCounter - 30'は負になります(ちなみに、定数を組み合わせて' ord(c) - intCounter - 33'を使用しませんか?)。その点、chr()文句を言う可能性があります。値が負の場合は256を追加する必要があります。または、モジュラス演算を使用して、に渡す0〜255の正の値を確保する必要がありますchr()。intCounterがどのようにインクリメントされるかがわからないため、0から255まで循環するのか、単調に増加するのかがわかりません。後者の場合、次のような式が必要です。

chr(mod(ord(c) - mod(intCounter, 255) + 479, 255))

ここで、もちろん256-33 = 223、および479 = 256 + 223です。これにより、渡される値chr()が正であり、任意の入力文字cおよびintCounterの任意の値に対して0..255の範囲にあることが保証されます(および、mod()関数のため負の引数を取得することはありませんmod()。引数が負の場合の動作に関係なく機能します)。

于 2008-11-08T06:08:07.047 に答える
0

それは、何らかの要求によって文字の ord() を変更するだけのひどいスキームで暗号化されているためです。そのため、データベースから出てくる文字列は暗号化されており、これにより復号化されます。上記で提供したものは機能していないようです。データベースでは latin-1 であり、django はそれを unicode に変換しますが、それを関数に unicode として渡すことはできませんが、latin-1 にエンコードしようとすると、そのエラーが表示されます。

于 2008-11-08T05:42:00.173 に答える