2011-01-18 59 views
7

Tôi muốn chuyển đổi số nguyên 32 byte (mặc dù tôi có thể cần độ dài khác) thành đối tượng byte trong python. Có cách nào đơn giản và sạch sẽ để làm điều này?Chuyển đổi n-byte int thành byte trong python3

+0

Định dạng nào có số nguyên hiện tại của bạn? –

+5

Số nguyên 32 byte? Đó là rất nhiều ... byte. Chính xác thì bạn đang cố gắng đạt được điều gì và bạn đã thử những gì? –

+0

Tôi có băm sha ở dạng 0x ..., python là hoàn toàn hạnh phúc chuyển đổi chúng thành số nguyên, nhưng làm thế nào để tôi nhận được từ đó đến byte? – Peter

Trả lời

3

Tôi đoán bạn cần một số nguyên 32-bit, và lớn về cuối nhỏ để khởi động:

>>> from ctypes import c_uint32 
>>> l = c_uint32(0x12345678) 
>>> bytes(l) 
b'xV4\x12' 

Có c_uint8, c_uint16 và c_uint64 là tốt. Đối với ints dài hơn, bạn cần phải làm cho nó bằng tay, bằng cách sử dụng divmod (x, 256).

>>> def bytify(v): 
... v, r = divmod(v, 256) 
... yield r 
... if v == 0: 
...  raise StopIteration 
... for r in bytify(v): 
...  yield r 
... 
>>> [x for x in bytify(0x12345678)] 
[120, 86, 52, 18] 
>>> bytes(bytify(0x12345678)) 
b'xV4\x12 
>>> bytes(bytify(0x1234567890987654321)) 
b'!Ce\x87\t\x89gE#\x01!Ce\x87\t\x89gE#\x01' 
+0

Không cần sử dụng ctypes: 'bytes' có thể được khởi tạo với một mảng' int 'trong phạm vi (0, 256). – Tom

+0

@Tom: Bạn chưa đọc toàn bộ câu trả lời. –

+0

Kính gửi @Lennart, bạn đã bắt đầu câu trả lời của bạn với nhập khẩu ctypes. Bạn tiếp tục hiển thị các loại xe có kích thước khác nhau. Sau đó, bạn cung cấp một giải pháp mà không sử dụng chúng (mà cá nhân tôi nghĩ rằng nên có được giải pháp đầu tiên) - mà không nói một cách rõ ràng. Tôi chỉ nghĩ rằng điều quan trọng là phải đề cập một cách rõ ràng sự thật, đó là tất cả. Bạn có quyền không đồng ý, và bạn không phải thuật lại câu trả lời nếu bạn không thấy nó phù hợp, nhưng không cần phải đưa ra lời buộc tội. Tôi đã nói những gì tôi nói bởi vì tôi nghĩ một số người có thể nhận được những ấn tượng sai lầm rằng ctypes là cần thiết và được nản chí bởi điều đó. – Tom

7

to_bytes (chiều dài, byteorder [ký]) là tất cả các bạn cần phải bắt đầu từ 3.2. Trong trường hợp này, số nhận dạng .to_bytes (4, 'big') sẽ cung cấp cho bạn chuỗi byte bạn cần.

+0

>>> hash.to_bytes (32) ... Traceback (cuộc gọi gần đây nhất): ... Tệp "", dòng 1, trong ... hash.to_bytes (32) ... AttributeError: đối tượng 'builtin_function_or_method' không có thuộc tính ... 'to_bytes' – Tom

+0

Lần sau tôi sẽ sử dụng một mã định danh khác; 'băm' có nghĩa là tên biến thực hoặc chữ, chứ không phải tên dựng sẵn. Tôi quên đã có một xây dựng như vậy, xấu của tôi. byteorder cũng được yêu cầu ngay bây giờ. – SilverbackNet

+0

Ồ, tôi đã nhầm lẫn - bây giờ tất cả đều rõ ràng, cảm ơn! – Tom

2

Bạn có thể sử dụng trực tiếp bytes("iterable"). Trong đó, mọi giá trị trong iterable sẽ cụ thể là byte trong bytes(). Ví dụ để mã hóa endian nhỏ:

>>> var=0x12345678 
>>> var_tuple=((var)&0xff, (var>>8)&0xff, (var>>16)&0xff, (var>>24)&0xff) 
>>> bytes(var_tuple) 
b'xV4\x12' 
1

Giả sử bạn có

var = 'і' # var is ukrainian і 

Chúng tôi muốn để có được nhị phân từ nó. Luồng này. value/là string => bytes => int => binary

binary_var = '{:b}'.format(int.from_bytes(var.encode('utf-8'), byteorder='big')) 

Bây giờ binary_var là '1101000110010110'. Nó gõ là chuỗi.

Bây giờ quay trở lại, bạn muốn nhận được giá trị unicode từ nhị phân:

int_var = int(binary_var, 2) # here we get int value, int_var = 53654 

Bây giờ chúng ta cần chuyển đổi số nguyên để byte. Ukraine 'і' không phải là sẽ phù hợp vào 1 byte nhưng trong 2. Chúng tôi chuyển đổi sang byte thực tế bytes_var = b '\ xd1 \ x96'

bytes_var = int_var.to_bytes(2, byteorder='big') 

Cuối cùng chúng ta giải mã byte của chúng tôi.

ukr_i = bytes_var.decode('utf-8') # urk_i = 'і' 
Các vấn đề liên quan