বাইটসের একটি স্ট্রিং কীভাবে একটি ইনটে রূপান্তর করবেন?


162

আমি কীভাবে বাইটসের একটি স্ট্রিংটিকে পাইথন-এ ইনট রূপান্তর করতে পারি?

এভাবে বলুন: 'y\xcc\xa6\xbb'

আমি এটি করার একটি চতুর / মূ way় উপায় নিয়ে এসেছি:

sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))

আমি জানি কিছু অন্তর্নির্মিত বা স্ট্যান্ডার্ড লাইব্রেরিতে থাকতে হবে যা এটি আরও সহজভাবে করে ...

এটি হেক্স ডিজিটের স্ট্রিংকে রূপান্তর করা থেকে পৃথক যার জন্য আপনি ইন্ট (xxx, 16) ব্যবহার করতে পারেন তবে পরিবর্তে আমি প্রকৃত বাইট মানগুলির একটি স্ট্রিং রূপান্তর করতে চাই।

হালনাগাদ:

আমি জেমসের উত্তরটি একটু ভালই পছন্দ করি কারণ এর জন্য অন্য মডিউল আমদানির প্রয়োজন হয় না, তবে গ্রেগের পদ্ধতিটি দ্রুত:

>>> from timeit import Timer
>>> Timer('struct.unpack("<L", "y\xcc\xa6\xbb")[0]', 'import struct').timeit()
0.36242198944091797
>>> Timer("int('y\xcc\xa6\xbb'.encode('hex'), 16)").timeit()
1.1432669162750244

আমার হ্যাকি পদ্ধতি:

>>> Timer("sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))").timeit()
2.8819329738616943

আরও আপডেট:

কেউ অন্য মডিউল আমদানি করতে সমস্যা কি মন্তব্য করেছে। ভাল, একটি মডিউল আমদানি করা অগত্যা সস্তা নয়, একবার দেখুন:

>>> Timer("""import struct\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""").timeit()
0.98822188377380371

মডিউলটি আমদানির ব্যয় সহ এই পদ্ধতির যে সমস্ত সুবিধা রয়েছে তা প্রায় উপেক্ষা করে। আমি বিশ্বাস করি যে এটি পুরো বেনমার্ক চালানোর জন্য একবারে এটি আমদানির ব্যয়কে অন্তর্ভুক্ত করবে; প্রতিবার পুনরায় লোড করার জন্য যখন জোর করে তখন কী হয় দেখুন:

>>> Timer("""reload(struct)\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""", 'import struct').timeit()
68.474128007888794

বলা বাহুল্য, যদি আপনি প্রতি ইম্পোর্টের তুলনায় এই পদ্ধতির প্রচুর সম্পাদন করছেন তবে এটি কোনও সমস্যার তুলনামূলকভাবে কম হয়ে যায়। এটি সম্ভবত সিপিইউর চেয়ে i / o ব্যয়ও তাই এটি নির্দিষ্ট মেশিনের ক্ষমতা এবং লোডের বৈশিষ্ট্যের উপর নির্ভর করে।


এবং স্ট্যান্ডার্ড লিব থেকে কিছু আমদানি করা খারাপ, কেন?


26
আপনার "আরও আপডেট" অদ্ভুত ... আপনি কেন এত ঘন ঘন মডিউলটি আমদানি করবেন?

5
আমি জানি এটি পুরানো প্রশ্ন। তবে আপনি যদি অন্য লোকের কাছে নিজের তুলনা টু ডেট রাখতে চান: আমার কম্পিউটারে মেকানিকাল শামুকের উত্তর ( int.from_bytes) কার্যকর করা যায় না struct.unpack। আরও পঠনযোগ্য ইমো হওয়ার পরে।
ম্যাগু_

উত্তর:


110

আপনি স্ট্রাকটি ব্যবহার করতে পারেন :

>>> struct.unpack("<L", "y\xcc\xa6\xbb")[0]
3148270713L

3
সতর্কতা: "এল" আসলে পাইথন 64৪ বিটের মধ্যে 8 বাইট (4 নয়), তাই এটি সেখানে ব্যর্থ হতে পারে।
রাফা ডগির্ড

12
রাফাł: সত্যই নয়, যেহেতু গ্রেগ <ব্যবহার করছিল, ডক্স অনুসারে এল মানক আকার (4) "যখন বিন্যাসের স্ট্রিং '<', '>', 'এর মধ্যে একটির সাথে শুরু হয়!' বা '='। " docs.python.org/library/struct.html# formatt
আন্দ্রে

59
এই উত্তরটি নির্বিচারে দৈর্ঘ্যের বাইনারি স্ট্রিংয়ের জন্য কাজ করে না।
amcnabb

4
প্রকারের নির্দিষ্ট আকার রয়েছে, এটি কখনই স্বেচ্ছাসেবী দৈর্ঘ্যের বাইনারি স্ট্রিংয়ের জন্য কাজ করবে না। আপনি যদি প্রতিটি আইটেমের প্রকারটি জানেন তবে এটি পরিচালনা করতে আপনি লুপের জন্য একটি সেট আপ করতে পারেন।
জোশুয়া ওলসন

2
"এল" আসলে uint32 (4 বাইট)। যদি আমার ক্ষেত্রে আপনার 8 বাইটের দরকার হয় তবে "Q" -> uint64 ব্যবহার করুন। এছাড়াও নোট করুন যে "l" -> int32 এবং q -> int64
ntg

319

পাইথন ৩.২ এবং তারপরে, ব্যবহার করুন

>>> int.from_bytes(b'y\xcc\xa6\xbb', byteorder='big')
2043455163

অথবা

>>> int.from_bytes(b'y\xcc\xa6\xbb', byteorder='little')
3148270713

অনুযায়ী endianness আপনার বাইট-স্ট্রিং এর।

এটি স্বেচ্ছাসেবী দৈর্ঘ্যের বাইটারেস্টিং-পূর্ণসংখ্যার জন্য এবং দু'টির পরিপূরক স্বাক্ষরিত পূর্ণসংখ্যার জন্য নির্দিষ্ট করে কাজ করে signed=True। এর জন্য দস্তাবেজগুলিfrom_bytes দেখুন ।


@ এরি কত ধীর? আমি স্ট্রাইক ব্যবহার করতাম তবে পিআই 3 এ যাওয়ার সময় int.from_bytes এ রূপান্তরিত হয়েছিল। আমি সিরিয়াল ডেটা পাচ্ছি বলে আমি এই পদ্ধতিটি প্রতি এমএসে কল করছি যাতে কোনও স্পিডআপ স্বাগত। আমি
নায়েব

@ নায়েব, os.urandom(4)বাইটের জন্য ** ১.৪ * এস ** (স্ট্রাক্ট) বনাম ** ২.৩ * এস ** (ইনট্রেফ্রোম_বাইটস) আমার সিপুতে। অজগর 3.5.2
এরি

5
@ অরি আমি বেশ কয়েকটি সিআরসি পদ্ধতি মূল্যায়নের জন্য ব্যবহৃত একটি টাইমিট স্ক্রিপ্টটি পুনরুত্থিত করেছি। চার রান 1) স্ট্রাক্ট 2) ইন্ট.ফ্রম_বাইট 3) # 1 হিসাবে তবে সিথন সংকলিত, 4) # 2 হিসাবে কিন্তু সিথন সংকলিত। স্ট্রাক্টের জন্য 330ns, ইনট-এর জন্য 1.14us (উভয় ক্ষেত্রে সিথন সম্ভবত 20ns স্পিডআপ দিয়েছে ...) দেখে মনে হচ্ছে আমি পিছনে ফিরে যাচ্ছি :) এটি অকাল অপটিমাইজেশন নয়, বিশেষত কয়েক মিলিয়ন নমুনা পোস্ট করার জন্য - প্রসেস এবং বন্ধ অংশ ছিটকে গেছে।
নায়েব

66

গ্রেগ যেমন বলেছিলেন, আপনি বাইনারি মানগুলি নিয়ে কাজ করে থাকেন তবে আপনি স্ট্রাক্ট ব্যবহার করতে পারেন, তবে আপনার যদি কেবল একটি "হেক্স নম্বর" থাকে তবে বাইট ফর্ম্যাটে আপনি কেবল এটিকে রূপান্তর করতে চাইতে পারেন:

s = 'y\xcc\xa6\xbb'
num = int(s.encode('hex'), 16)

... এটি একই:

num = struct.unpack(">L", s)[0]

... বাদে এটি কোনও সংখ্যক বাইটের জন্য কাজ করবে।


3
"বাইনারি মানগুলি" এবং "" হেক্স নম্বর "তবে বাইট ফর্ম্যাটে" ???????

"সহায়তা কাঠামো" দেখুন। যেমন। "001122334455" .ডেকোড ('হেক্স') স্ট্রাক্ট ব্যবহার করে কোনও সংখ্যায় রূপান্তর করা যায় না।
জেমস এন্টিল

3
যাইহোক, এই উত্তরটি অনুমান করে যে পূর্ণসংখ্যাটি বড়-এন্ডিয়ান বাইট ক্রমে এনকোড করা হয়েছে। লিটল-এন্ডিয়ান অর্ডারের জন্য, করুন:int(''.join(reversed(s)).encode('hex'), 16)
amcnabb

1
ভাল তবে এটি ধীর হতে চলেছে! অনুমান করুন যে আপনি পাইথনে কোডিং দিচ্ছেন তা সত্যিই কিছু যায় আসে না।
ম্যাটকোচরন

8

আমি ইনট, হেক্স এবং বাইটের মধ্যে ডেটা রূপান্তর করতে নিম্নলিখিত ফাংশনটি ব্যবহার করি।

def bytes2int(str):
 return int(str.encode('hex'), 16)

def bytes2hex(str):
 return '0x'+str.encode('hex')

def int2bytes(i):
 h = int2hex(i)
 return hex2bytes(h)

def int2hex(i):
 return hex(i)

def hex2int(h):
 if len(h) > 1 and h[0:2] == '0x':
  h = h[2:]

 if len(h) % 2:
  h = "0" + h

 return int(h, 16)

def hex2bytes(h):
 if len(h) > 1 and h[0:2] == '0x':
  h = h[2:]

 if len(h) % 2:
  h = "0" + h

 return h.decode('hex')

সূত্র: http://opentechnotes.blogspot.com.au/2014/04/convert-values-to-from-integer-hex.html


6
import array
integerValue = array.array("I", 'y\xcc\xa6\xbb')[0]

সতর্কতা: উপরেরটি দৃ strongly়ভাবে প্ল্যাটফর্ম-নির্দিষ্ট। "আমি" নির্দিষ্টকরণকারী এবং স্ট্রিং-> ইন্ট রূপান্তরটির শেষতা উভয়ই আপনার নির্দিষ্ট পাইথন প্রয়োগের উপর নির্ভরশীল। তবে আপনি যদি একবারে অনেকগুলি পূর্ণসংখ্যা / স্ট্রিং রূপান্তর করতে চান তবে অ্যারে মডিউলটি এটি দ্রুত করে।


5

পাইথন ২.x এ, আপনি <Bস্বাক্ষরবিহীন বাইটগুলির <bজন্য এবং struct.unpack/struct.pack

উদাহরণ:

চলুন x='\xff\x10\x11'

data_ints = struct.unpack('<' + 'B'*len(x), x) # [255, 16, 17]

এবং:

data_bytes = struct.pack('<' + 'B'*len(data_ints), *data_ints) # '\xff\x10\x11'

যে *প্রয়োজন!

দেখা বিন্যাস নির্দিষ্টকরণের তালিকার জন্য https://docs.python.org/2/library/struct.html#format-characters cha


3
>>> reduce(lambda s, x: s*256 + x, bytearray("y\xcc\xa6\xbb"))
2043455163

পরীক্ষা 1: বিপরীত:

>>> hex(2043455163)
'0x79cca6bb'

পরীক্ষা 2: বাইট সংখ্যা> 8:

>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAAA"))
338822822454978555838225329091068225L

পরীক্ষা 3: এক দ্বারা বৃদ্ধি:

>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAAB"))
338822822454978555838225329091068226L

পরীক্ষা 4: একটি বাইট যুক্ত করুন, 'এ' বলুন:

>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAABA"))
86738642548474510294585684247313465921L

পরীক্ষা 5: 256 দ্বারা ভাগ করুন:

>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAABA"))/256
338822822454978555838225329091068226L

আশানুরূপ ফলাফল টেস্ট 4 এর ফলাফলের সমান।


1

পাইথন ২.x এর অধীনে কাজ করতে হবে এমন নির্বিচারে দৈর্ঘ্য বাইট সিকোয়েন্সগুলির জন্য একটি সমাধান খুঁজতে আমি সংগ্রাম করে যাচ্ছিলাম শেষ পর্যন্ত আমি এটি লিখেছিলাম, এটি কিছুটা হ্যাকি কারণ এটি একটি স্ট্রিং রূপান্তর সম্পাদন করে, তবে এটি কার্যকর হয়।

পাইথন ২.x এর কার্যকারিতা, স্বেচ্ছাসেবী দৈর্ঘ্য

def signedbytes(data):
    """Convert a bytearray into an integer, considering the first bit as
    sign. The data must be big-endian."""
    negative = data[0] & 0x80 > 0

    if negative:
        inverted = bytearray(~d % 256 for d in data)
        return -signedbytes(inverted) - 1

    encoded = str(data).encode('hex')
    return int(encoded, 16)

এই ফাংশনটির দুটি প্রয়োজনীয়তা রয়েছে:

  • ইনপুটটি dataএকটি হওয়া দরকার bytearray। আপনি এইভাবে ফাংশনটি কল করতে পারেন:

    s = 'y\xcc\xa6\xbb'
    n = signedbytes(s)
  • ডেটাটি বড়-এন্ডিয়ান হতে হবে। আপনার যদি সামান্য এন্ডিয়ান মান থাকে তবে আপনার প্রথমে এটির বিপরীত হওয়া উচিত:

    n = signedbytes(s[::-1])

অবশ্যই, যদি স্বেচ্ছাসেবী দৈর্ঘ্যের প্রয়োজন হয় তবে এটি ব্যবহার করা উচিত। অন্যথায়, আরও মানক উপায় (উদাহরণস্বরূপ struct) দিয়ে আঁকুন ।


1

আপনি সংস্করণ> = 3.2 এ থাকলে int.from_bytes সেরা সমাধান। "স্ট্রাক্ট.নপ্যাক" সমাধানের জন্য একটি স্ট্রিং দরকার তাই এটি বাইটের অ্যারেগুলিতে প্রযোজ্য হবে না। এখানে আরও একটি সমাধান:

def bytes2int( tb, order='big'):
    if order == 'big': seq=[0,1,2,3]
    elif order == 'little': seq=[3,2,1,0]
    i = 0
    for j in seq: i = (i<<8)+tb[j]
    return i

হেক্স (বাইটস 2int ([0x87, 0x65, 0x43, 0x21])) '0x87654321' প্রদান করে।

এটি বড় এবং সামান্য endianness পরিচালনা করে এবং 8 বাইট জন্য সহজেই পরিবর্তনযোগ্য


1

উপরে স্ট্রাক্টunpack ফাংশন ব্যবহার করে উল্লিখিত একটি ভাল উপায়। আপনি যদি নিজের ফাংশনটি বাস্তবায়ন করতে চান তবে অন্য একটি সমাধান রয়েছে:

def bytes_to_int(bytes):
    result = 0
    for b in bytes:
        result = result * 256 + int(b)
return result

এটি নেতিবাচক সংখ্যার জন্য কাজ করে না যা বাইটে রূপান্তরিত হয়েছিল।
মারিয়া

1

পাইথন 3 এ আপনি সহজেই একটি বাইট স্ট্রিংকে পূর্ণসংখ্যার (0..255) তালিকায় রূপান্তর করতে পারেন

>>> list(b'y\xcc\xa6\xbb')
[121, 204, 166, 187]

0

অ্যারে.আররে ব্যবহার করে একটি শালীন গতিযুক্ত পদ্ধতি আমি কিছু সময়ের জন্য ব্যবহার করছি:

পূর্বনির্ধারিত ভেরিয়েবলগুলি:

offset = 0
size = 4
big = True # endian
arr = array('B')
arr.fromstring("\x00\x00\xff\x00") # 5 bytes (encoding issues) [0, 0, 195, 191, 0]

টু ইনট: (পড়ুন)

val = 0
for v in arr[offset:offset+size][::pow(-1,not big)]: val = (val<<8)|v

int থেকে: (লিখুন)

val = 16384
arr[offset:offset+size] = \
    array('B',((val>>(i<<3))&255 for i in range(size)))[::pow(-1,not big)]

যদিও এগুলি আরও দ্রুত হতে পারে।

সম্পাদনা:
কিছু সংখ্যার জন্য, এখানে একটি পারফরম্যান্স টেস্ট (অ্যানাকোন্ডা ২.৩.০) তুলনায় তুলনায় পড়তে স্থিতিশীল গড় দেখায় reduce():

========================= byte array to int.py =========================
5000 iterations; threshold of min + 5000ns:
______________________________________code___|_______min______|_______max______|_______avg______|_efficiency
⣿⠀⠀⠀⠀⡇⢀⡀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⡀⠀⢰⠀⠀⠀⢰⠀⠀⠀⢸⠀⠀⢀⡇⠀⢀⠀⠀⠀⠀⢠⠀⠀⠀⠀⢰⠀⠀⠀⢸⡀⠀⠀⠀⢸⠀⡇⠀⠀⢠⠀⢰⠀⢸⠀
⣿⣦⣴⣰⣦⣿⣾⣧⣤⣷⣦⣤⣶⣾⣿⣦⣼⣶⣷⣶⣸⣴⣤⣀⣾⣾⣄⣤⣾⡆⣾⣿⣿⣶⣾⣾⣶⣿⣤⣾⣤⣤⣴⣼⣾⣼⣴⣤⣼⣷⣆⣴⣴⣿⣾⣷⣧⣶⣼⣴⣿⣶⣿⣶
    val = 0 \nfor v in arr: val = (val<<8)|v |     5373.848ns |   850009.965ns |     ~8649.64ns |  62.128%
⡇⠀⠀⢀⠀⠀⠀⡇⠀⡇⠀⠀⣠⠀⣿⠀⠀⠀⠀⡀⠀⠀⡆⠀⡆⢰⠀⠀⡆⠀⡄⠀⠀⠀⢠⢀⣼⠀⠀⡇⣠⣸⣤⡇⠀⡆⢸⠀⠀⠀⠀⢠⠀⢠⣿⠀⠀⢠⠀⠀⢸⢠⠀⡀
⣧⣶⣶⣾⣶⣷⣴⣿⣾⡇⣤⣶⣿⣸⣿⣶⣶⣶⣶⣧⣷⣼⣷⣷⣷⣿⣦⣴⣧⣄⣷⣠⣷⣶⣾⣸⣿⣶⣶⣷⣿⣿⣿⣷⣧⣷⣼⣦⣶⣾⣿⣾⣼⣿⣿⣶⣶⣼⣦⣼⣾⣿⣶⣷
                  val = reduce( shift, arr ) |     6489.921ns |  5094212.014ns |   ~12040.269ns |  53.902%

এটি একটি কাঁচা পারফরম্যান্স পরীক্ষা, সুতরাং এন্ডিয়ান পাও-ফ্লিপটি বাদ যায়। দেখানো ফাংশন লুপ জন্য একই Shift-oring অপারেশন প্রযোজ্য হয় এবং ঠিক হয় পাশে দ্রুততম পুনরাবৃত্ত কর্মক্ষমতা রয়েছে যেমন ।
shiftarrarray.array('B',[0,0,255,0])dict

আমার সম্ভবত এও লক্ষ্য করা উচিত যে দক্ষতা গড় সময়ের সাথে নির্ভুলতা দ্বারা পরিমাপ করা হয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.