পাইথন কিভাবে বাইনারি ফাইল লিখবেন?


128

আমার কাছে পূর্ণসংখ্যার হিসাবে বাইটের একটি তালিকা রয়েছে যা এরকম কিছু

[120, 3, 255, 0, 100]

বাইনারি হিসাবে কোনও ফাইলটিতে এই তালিকাটি কীভাবে লিখতে পারি?

এই কাজ করবে?

newFileBytes = [123, 3, 255, 0, 100]
# make file
newFile = open("filename.txt", "wb")
# write to file
newFile.write(newFileBytes)

60
আপনি জিজ্ঞাসা "এই কাজ করবে?"। আপনি কি এটা চেষ্টা করেছেন?
স্টিফেনটিজি

1
হওয়া উচিত TypeError: argument 1 must be string or buffer, not list
অ্যানাটোলি টেকটোনিক

উত্তর:


128

এটি ঠিক এটির bytearrayজন্য:

newFileByteArray = bytearray(newFileBytes)
newFile.write(newFileByteArray)

আপনি যদি পাইথন ৩.x ব্যবহার করছেন তবে আপনি এর bytesপরিবর্তে ব্যবহার করতে পারেন (এবং সম্ভবত এটি করা উচিত, কারণ এটি আপনার উদ্দেশ্যকে আরও ভালভাবে নির্দেশ করে)। তবে পাইথন ২.x এ এটি কার্যকর হবে না, কারণ bytesএটি কেবলমাত্র একটি উপনাম str। যথারীতি, ইন্টারেক্টিভ ইন্টারপ্রেটারের সাথে পাঠ্য দিয়ে ব্যাখ্যা করা আরও সহজ, সুতরাং আমাকে কেবল এটি করতে দিন।

পাইথন 3.x:

>>> bytearray(newFileBytes)
bytearray(b'{\x03\xff\x00d')
>>> bytes(newFileBytes)
b'{\x03\xff\x00d'

পাইথন 2.x:

>>> bytearray(newFileBytes)
bytearray(b'{\x03\xff\x00d')
>>> bytes(newFileBytes)
'[123, 3, 255, 0, 100]'

1
বিল্টিন ধরণের দুর্দান্ত ব্যবহার কেবলমাত্র নোট করুন যে বাইটায়ারে ২.6-এ যুক্ত করা হয়েছিল, আপনি যদি উত্তরাধিকার ব্যবস্থাটি সমর্থন করতে চান তবে এটি এড়ানো উচিত।
পার্কিনস

7
@ পারকিনস: অবশ্যই, এবং আপনার যদি জেনারেটর এক্সপ্রেশনগুলি এড়ানো উচিত যদি আপনার ২.৩-তে কাজ করা দরকার হয় তবে উভয়ের সাথে সাবধান হন str.encodeএবং আপনার struct.packযদি ২.২-তে কাজ করার প্রয়োজন হয়। তবে ২.6 এখন ৫ বছরের জন্য বাইরে রয়েছে; তিনটি উবুন্টু এলটিএস এখনও সমর্থনে রয়েছে, সমর্থিত তিনটি ওএস এক্স সংস্করণ, সেন্টোস / আরএইচইল ইত্যাদির পূর্ববর্তী বড় সংস্করণ ইত্যাদি সমস্ত এটি অন্তর্নির্মিত সাথে আসে you আপনার যদি 2.5 বা 2.1 বা 1.6 বা যা কিছু সমর্থন করতে হয় তবে আপনি সম্ভবত
জানুন

4
উইন্ডোজে পাইথন 2 সহ, আমি দেখতে পেলাম যে ফাইলটি খোলার সময় "বি" পতাকাটি পাস না করা হলে, বাইনারি ডেটার জন্য এটি একটি bytearrayএখনও রূপান্তরিত \nকরে \r\nএটি বাইনারি ডেটার জন্য অসন্তুষ্ট করে তোলে is
ফেয়ারসাম

6
@ ফেয়ারসাম: অবশ্যই; বাইনারি বনাম টেক্সট মোড এর অর্থ 2.x. আপনার বাইটগুলি কী ধরণের থেকে আসে তা বিবেচ্য নয়। (অবশ্যই \r\n
x

আমি নিশ্চিত নই যে বাইটায়ারে () ফাইল লেখার জন্য একটি ভাল পছন্দ। আপনার মাপটি পরিচালনাযোগ্য খণ্ডগুলির মধ্যে সীমাবদ্ধ করতে হবে। অন্যথায় একবার যদি আপনার ফাইল আকারগুলি খুব বেশি হয়ে যায় আপনি মেমরির বাইরে চলে যাবেন।
ম্যাকেনজম

31

ব্যবহার করুন struct.packবাইনারি বাইট মধ্যে পূর্ণসংখ্যা মান রূপান্তর, তারপর বাইট লিখুন। যেমন

newFile.write(struct.pack('5B', *newFileBytes))

তবে আমি কখনই বাইনারি ফাইলকে .txtএক্সটেনশন দেব না ।

এই পদ্ধতির সুবিধাটি হ'ল এটি অন্যান্য ধরণের ক্ষেত্রেও কাজ করে, উদাহরণস্বরূপ যদি মানগুলির কোনও 255 এর চেয়ে বেশি হয় তবে আপনি '5i'32-বিট পূর্ণ পূর্ণসংখ্যার পরিবর্তে বিন্যাসের জন্য ব্যবহার করতে পারেন ।


.txt ঠিক আছে যদি আপনার জানার কিছু উপায় থাকে যে আপনি যে সমস্ত ডেটা লিখছেন তা মুদ্রণযোগ্য আসকি পরিসরের মধ্যে পড়ে। তবে, আপনি সঠিক বলেছেন আমি এই ক্ষেত্রে মনে করি, উদাহরণস্বরূপ ডেটাতে প্রিন্টযোগ্য অক্ষর অন্তর্ভুক্ত রয়েছে।
পার্কিনস

@ পারকিনস আমি এই ধারণাটি করিনি যে আসকগুলি ASCII সীমার মধ্যে 256 এরও কম হবে। এমনকি যদি তা হয় তবে .txt ফাইলগুলি এমন কোনও ব্যক্তির জন্য সংরক্ষণ করা উচিত যা কোনও বাইনারি ডেটার ক্ষেত্রে কখনও প্রয়োগ হয় না।
মার্ক র্যানসোম

1
আপনি ঠিক বলেছেন, স্ট্রাক্ট.প্যাকটি 255 এর উপরে মান সহ ডেটা লিখতে যাচ্ছেন এমনও উপায়, যেহেতু বাইটারি বা ক্রিয়াল উভয়ই বৃহত্তর পূর্ণসংখ্যার মানগুলি পরিচালনা করতে পারে না।
পারকিনস

1
@ মার্কারান্সম: আচ্ছা, "আমার কাছে কিছু স্বেচ্ছাচারিত কিন্তু স্থির আকারের পূর্ণসংখ্যার একটি তালিকা রয়েছে, আমি কীভাবে এগুলিকে বাইনারি ফাইলে লিখব?" এবং আমি লোকেরা এই প্রশ্নটি অনুসন্ধান করতে এবং
এটির

1
স্ট্রাক্ট.প্যাক আরও ভাল উত্তর; এটি কেবলমাত্র বাইট্রে তৈরির চেয়ে অনেক বেশি নমনীয়।
শেঠ

12

পূর্ণসংখ্যা <256 থেকে বাইনারি রূপান্তর করতে, chrফাংশনটি ব্যবহার করুন । সুতরাং আপনি নিম্নলিখিত করছেন খুঁজছেন।

newFileBytes=[123,3,255,0,100]
newfile=open(path,'wb')
newfile.write((''.join(chr(i) for i in newFileBytes)).encode('charmap'))

1
আপনার অর্থ অবশ্যই <128. পাইথন 3 অভিযোগ করে: ইউনিকোড এনকোড এরিয়ার: 'এসকিআই' কোডেক '' x89 'পজিশনে অক্ষরটি এনকোড করতে পারে না: সীমিত নয় (128)
এলি

2
না, আমার অর্থ <256 তবে এনকোডিংটি এর charmapচেয়ে বেশি হওয়া উচিত asciiএবং পাইথন 2 পাশাপাশি পাইথন 3 এ কাজ করে। asciiএনকোডিং শুধুমাত্র python2 কাজ করে।
পার্কিনস

9

পাইথন ৩.২++ অনুসারে, আপনি to_bytesদেশীয় অভ্যন্তরীণ পদ্ধতি ব্যবহার করে এটিও সম্পন্ন করতে পারেন :

newFileBytes = [123, 3, 255, 0, 100]
# make file
newFile = open("filename.txt", "wb")
# write to file
for byte in newFileBytes:
    newFile.write(byte.to_bytes(1, byteorder='big'))

অর্থাত্, to_bytesএই ক্ষেত্রে প্রতিটি একক কল দৈর্ঘ্যের 1 টি স্ট্রিং তৈরি করে, এর অক্ষরগুলি বড়-এন্ডিয়ান ক্রমে সাজানো (যা দৈর্ঘ্য -1 স্ট্রিংয়ের জন্য তুচ্ছ), যা পূর্ণসংখ্যার মান উপস্থাপন করে byte। আপনি শেষ দুটি লাইন একটি এককতে সংক্ষিপ্তও করতে পারেন:

newFile.write(''.join([byte.to_bytes(1, byteorder='big') for byte in newFileBytes]))

8

পাইথন 3 সিনট্যাক্স ব্যবহার করে আপনি নিম্নলিখিত কোড উদাহরণটি ব্যবহার করতে পারেন:

from struct import pack
with open("foo.bin", "wb") as file:
  file.write(pack("<IIIII", *bytearray([120, 3, 255, 0, 100])))

এখানে শেল ওয়ান লাইনার রয়েছে:

python -c $'from struct import pack\nwith open("foo.bin", "wb") as file: file.write(pack("<IIIII", *bytearray([120, 3, 255, 0, 100])))'

1

এর মতো আচার ব্যবহার করুন: আচার আমদানি করুন

আপনার কোডটি দেখতে এই রকম হবে:

import pickle
mybytes = [120, 3, 255, 0, 100]
with open("bytesfile", "wb") as mypicklefile:
    pickle.dump(mybytes, mypicklefile)

ডেটাটি আবার পড়তে, পিকেল.লোড পদ্ধতিটি ব্যবহার করুন


3
এটি 5 বাইট দৈর্ঘ্যের একটি বাইনারি ফাইল তৈরি করে না, যেখানে কেবলমাত্র সামগ্রীটি 120, 3, 255, 0, 100 a
পারভাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.