13

ご存知のように、コンピュータは数字を扱います。私は今、このテキストを入力しています。サーバーはそれから数字を作成し、それを読みたいときに、サーバーからテキストを取得します。

どうすれば自分でこれを行うことができますか?

独自のアルゴリズムで何かを暗号化したいのですが、アルゴリズムは整数で問題なく動作しますが、文字列を暗号化したいのですが、Unicode 文字列を整数に、またはその逆に変換する方法がわかりません。

私は Python 3 を使用しています。私の問題に対する洗練された解決策を知っている人はいますか?

4

5 に答える 5

17

ord()あなたは関数を探しています、私は思う:

>>> ord('a')
97
>>> ord('\u00c2')
192

これにより、Unicode コードポイントの整数が得られます。

文字セット全体を変換するには、リスト内包表記を使用します。

>>> [ord(c) for c in 'Hello World!']
[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]

chr()関数は次のとおりです。

>>> chr(97)
'a'
>>> chr(193)
'Á'

復号化テキストを暗号化するときは、通常、テキストを文字エンコーディングでバイナリ表現にエンコードすることに注意してください。Unicode テキストは、さまざまな長所と短所を持つさまざまなエンコーディングでエンコードできます。最近では、Unicode テキストUTF-8に最も一般的に使用されるエンコーディングですが、他のエンコーディングも存在します。

Python 3 では、バイナリ データはbytesobjectで表され、str.encode()メソッドを使用してテキストをバイトにエンコードし、次を使用して戻りますbytes.decode()

>>> 'Hello World!'.encode('utf8')
b'Hello World!'
>>> b'Hello World!'.decode('utf8')
'Hello World!'

bytes値は、リストやタプル、文字列などの単なるシーケンスですが、0 ~ 255 の整数で構成されています。

>>> list('Hello World!'.encode('utf8'))
[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]

個人的には、暗号化するときは、結果のバイトをエンコードして暗号化する必要があります。

これらすべてが圧倒されたり、理解するのが難しいと思われる場合は、Unicode と文字エンコーディングに関する次の記事が役立つ可能性があります。

于 2012-09-27T16:12:23.917 に答える
12

Unicode文字列を数値に変換する通常の方法は、それをバイトシーケンスに変換することです。Unicode文字は純粋な抽象化であり、各文字には独自の番号があります。ただし、数値をバイトのストリームに変換する方法は他にもあります。おそらくそれを行う最も用途の広い方法は、文字列をUTF-8エンコーディングにエンコードすることです。あなたはそれから整数を得る多くの方法を選ぶことができます。これが1つです(私はIvellaから素敵な文字列を借りました-悪い言葉が中にないことを願っています:):

Python 3.2.1 (default, Jul 10 2011, 20:02:51) [MSC v.1500 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> s = "Hello, World, عالَم, ދުނިޔެ, जगत, 世界"
>>> b = s.encode('utf-8')
>>> b
b'Hello, World, \xd8\xb9\xd8\xa7\xd9\x84\xd9\x8e\xd9\x85, \xde\x8b\xde\xaa\xde\x82\xde\xa8\xde\x94\xde\xac, \xe0\xa4\x9c\xe0\xa4\x97\xe0\xa4\xa4, \xe4\xb8\x96\xe7\x95\x8c'

これで、128〜255の番号のバイトが16進数でコード化されたエスケープシーケンスとして表示されるバイトシーケンスができました。すべてのバイトをバイト文字列として16進コードに変換してみましょう。

>>> import binascii
>>> h = binascii.hexlify(b)
>>> h
b'48656c6c6f2c20576f726c642c20d8b9d8a7d984d98ed9852c20de8bdeaade82dea8de94deac2c20e0a49ce0a497e0a4a42c20e4b896e7958c'

そして、16進表記で(テキストとして)書かれた大きな数としてそれを見ることができます。intを使用すると、それを抽象数に変換できます。これは、印刷されると、通常は10進表記に変換されます。

>>> i = int(h, 16)
>>> i
52620351230730152682202055464811384749235956796562762198329268116226267262806875102376740945811764490696968801603738907493997296927348108

これで、数値として保存し、暗号化して(ただし、以前のバイトシーケンスを暗号化するのが一般的です)、後で整数に変換し直すことができます。その大きな整数を処理できる言語は多くない(そしておそらくデータベースがない)ことに注意してください。

元の文字列に戻りましょう。まず、16進表現(文字列)に変換します。

>>> h2 = hex(i)
>>> h2
'0x48656c6c6f2c20576f726c642c20d8b9d8a7d984d98ed9852c20de8bdeaade82dea8de94deac2c20e0a49ce0a497e0a4a42c20e4b896e7958c'
>>> h3 = h2[2:]   # remove the 0x from the beginning
>>> h3
'48656c6c6f2c20576f726c642c20d8b9d8a7d984d98ed9852c20de8bdeaade82dea8de94deac2c20e0a49ce0a497e0a4a42c20e4b896e7958c'
>>> type(h3)
<class 'str'>

0x残りは数字を表す16進文字であるとだけ書かれているので、を削除する必要がありました。h3strタイプであることに注意してください。Python 3(上部を参照)の場合、strはUnicode文字列を意味します。次のステップは、6つの数字のカップルをバイトに戻すことです。試してみましょうunhexlify()

>>> binascii.unhexlify(h3)
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    binascii.unhexlify(h3)
TypeError: 'str' does not support the buffer interface

おっと!バイト文字列のみを受け入れます。次に、Unicodeの各16進数をバイト文字列の16進数にエンコードします。行く方法はエンコードすることです。ただし、ASCIIへのエンコードは簡単です。

>>> b2 = h3.encode('ascii')  # character by character; subset of ascii only
>>> b2
b'48656c6c6f2c20576f726c642c20d8b9d8a7d984d98ed9852c20de8bdeaade82dea8de94deac2c20e0a49ce0a497e0a4a42c20e4b896e7958c'
>>> b3 = binascii.unhexlify(b2)
>>> b3
b'Hello, World, \xd8\xb9\xd8\xa7\xd9\x84\xd9\x8e\xd9\x85, \xde\x8b\xde\xaa\xde\x82\xde\xa8\xde\x94\xde\xac, \xe0\xa4\x9c\xe0\xa4\x97\xe0\xa4\xa4, \xe4\xb8\x96\xe7\x95\x8c'

これで、最初の。の後と同様のバイト文字列ができました.encode('utf-8')。逆の操作を使用してみましょう-UTF-8からデコードします。最初に使用したものと同じUnicode文字列を取得する必要があります。

>>> s2 = b3.decode('utf-8')
>>> s2
'Hello, World, عالَم, ދުނިޔެ, जगत, 世界'
>>> s == s2   # is the original equal to the result?
True

:)

于 2012-09-27T18:32:26.260 に答える
8

pythonのドキュメントから:

binasciiモジュールには、バイナリとさまざまな ASCII エンコードされたバイナリ表現との間で変換を行うための多数のメソッドが含まれています。

たとえば、バイナリ文字列「LOL」binascii.hexlifyの 16 進数表現を取得し、 int組み込み関数を使用して整数に変換するために使用できます。

>>> binascii.hexlify(b"LOL")
b'4c4f4c'
>>> int(binascii.hexlify(b"LOL"), 16)
5001036

これを Unicode 文字列に適用する必要があるため、最初にそれらをバイナリ文字列としてエンコードする必要があります。str.encodeこの目的のためにメソッドを使用できます。

>>> int(binascii.hexlify("fiŝaĵo".encode("utf-8")), 16)
7379646744164087151

それでおしまい。

逆の場合は、各ステップを逆にする必要があります。最初に整数を 16 進表現でバイナリ文字列として変換し (使用しformat(int, "x")てからエンコードできます)、ASCII で 16 進数を変換しbinascii.unhexlify、最後に utf-8 としてデコードします。

>>> binascii.unhexlify(format(7379646744164087151, "x").encode("utf-8")).decode("utf-8")
'fiŝaĵo'

以上が順を追った説明でしたが、本当にこの機能を使うのであれば、関数の形に整理するとよいでしょう。

于 2012-09-27T18:45:57.537 に答える
2

Martijn Pieters によって提供されたソリューションに基づいて構築すると、文字列を巨大な数にすることができます。Python 3 は、int 型が任意に大きいため、非常にうまく処理できます (これは「コンピューターの仕組み」ではありません。質問に対する私の解説を参照してください)。 .

文字数値コードのリストが与えられた場合:

>>> a = [ord(c) for c in 'Hello World!']
>>> print(a)
[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]

そして、 Unicodeに関するウィキペディアのページから、最大の Unicode 文字数が 10FFFF (16 進数) であることを知っていれば、次のことができます。

def numfy(s):
    number = 0
    for e in [ord(c) for c in s]:
        number = (number * 0x110000) + e
    return number

def denumfy(number):
    l = []
    while(number != 0):
        l.append(chr(number % 0x110000))
        number = number // 0x110000
    return ''.join(reversed(l))

したがって:

>>> a = numfy("Hello, World, عالَم, ދުނިޔެ, जगत, 世界")
>>> a
31611336900126021[...]08666956
>>> denumfy(a)
'Hello, World, عالَم, ދުނިޔެ, जगत, 世界'

この 0x110000 (10FFFF + 1 から) は、予想されるさまざまな Unicode 文字の数 (1114112、10 進数) です。英語のアルファベットのみを使用していることが確実な場合は、ここで 128 を使用できます。また、アクセント付きのラテン語を使用している場合は、256 を使用しても安全です。いずれにせよ、数字ははるかに小さくなりますが、すべての Unicode 文字を表します。

于 2012-09-27T17:24:32.437 に答える
-1

これにより、各文字が数字に変換されます...

s="hello \u2020"
print [ord(c) for c in s]
于 2012-09-27T16:15:38.663 に答える