2009-07-22 30 views
54

में बाइनरी फ़ाइल से पूर्णांक पढ़ना मैं पाइथन में BMP फ़ाइल पढ़ने की कोशिश कर रहा हूं। मुझे पता है कि पहले दो बाइट बीएमपी फर्म को इंगित करते हैं। अगले 4 बाइट फ़ाइल आकार हैं। जब मैं निष्पादित करें:पाइथन

fin = open("hi.bmp", "rb") 
firm = fin.read(2) 
file_size = int(fin.read(4)) 

मैं

ValueError: invalid literal for int() with base 10: 'F#\x13'

मिल रहा करने के लिए एक पूर्णांक के रूप में उन चार बाइट्स पढ़ रही है चाहते हैं क्या ... ऐसा लगता है अजगर उन्हें पात्रों के रूप में पढ़ रहे हैं और एक स्ट्रिंग, लौटा रहा है जो एक पूर्णांक में परिवर्तित नहीं किया जा सकता है। मैं इसे सही तरीके से कैसे कर सकता हूं?

+2

यदि आपका लक्ष्य * अपनी बीएमपी लाइब्रेरी लिखने में समय बिताने के बजाय बिटमैप का उपयोग करना है (ऐसा नहीं है कि यह मजेदार लगता है ...) तो आप पीआईएल का उपयोग कर सकते हैं http://www.pythonware.com/ उत्पाद/पायल/जो आप पहले ही स्थापित कर चुके हैं। आज़माएं: आयात छवि –

+4

धन्यवाद जेरेड, लेकिन मैं मजेदार होने के लिए मैन्युअल रूप से बीएमपी पढ़ना चाहता था! :) –

उत्तर

88

read विधि एक स्ट्रिंग के रूप में बाइट्स का अनुक्रम देता है। स्ट्रिंग बाइट-अनुक्रम से बाइनरी डेटा में कनवर्ट करने के लिए, अंतर्निहित struct मॉड्यूल का उपयोग करें: http://docs.python.org/library/struct.html

import struct 

print(struct.unpack('i', fin.read(4))) 

ध्यान दें कि unpack हमेशा एक टपल देता है, तो struct.unpack('i', fin.read(4))[0] पूर्णांक मान है कि आप के बाद कर रहे हैं देता है।

आप शायद प्रारूप स्ट्रिंग '<i' का उपयोग करना चाहिए (< एक आपरिवर्तक है कि छोटी-endian बाइट-क्रम और मानक आकार और संरेखण इंगित करता है - डिफ़ॉल्ट मंच की बाइट आदेश, आकार और संरेखण उपयोग करने के लिए है)। बीएमपी प्रारूप के अनुसार, बाइट इंटेल/छोटे-एंडियन बाइट ऑर्डर में लिखा जाना चाहिए।

+18

लिखने के बजाय 'i = struct.unpack (...) [0] 'मैं अक्सर लिखता हूं' i, = struct.unpack (...)' –

+0

@Ototo क्या कोई कारण है कि आप एक तरफ पसंद करते हैं अन्य? क्या कोई तार्किक अंतर है? – Caltor

+1

मुझे यह आश्चर्य की बात है कि पाइथन में एक फ़ाइल से पूर्णांक (या शॉर्ट्स इत्यादि) पढ़ने के लिए अंतर्निहित फ़ंक्शन नहीं है। मैं कोई जावा विशेषज्ञ नहीं हूं लेकिन मेरा मानना ​​है कि इसमें मूल कार्य हैं जैसे readUnsignedShort() ऐसा करने के लिए। – Caltor

4

आप बाइनरी फ़ाइल पढ़ रहे हैं के रूप में, क्या आप भी array मॉड्यूल

import array 
values = array.array('l') # array of long integers 
values.read(fin, 1) # read 1 integer 
file_size = values[0] 
+0

struct.unpack एक tuple – luc

+0

@luc देता है, धन्यवाद, तय –

6

के लिए struct मॉड्यूल का उपयोग करने की आवश्यकता है वैकल्पिक विधि जो 'struct.unpack()' का उपयोग नहीं करती है, NumPy का उपयोग करना होगा:

import numpy as np 

f = open("file.bin", "r") 
a = np.fromfile(f, dtype=np.uint32) 

'dtype' डेटाटाइप का प्रतिनिधित्व करता है और int #, uint #, float #, जटिल # या उपयोगकर्ता परिभाषित प्रकार हो सकता है। numpy.fromfile देखें।

व्यक्तिगत रूप से सरणी/मैट्रिक्स डेटा के साथ काम करने के लिए NumPy का उपयोग करना पसंद करते हैं क्योंकि यह पाइथन सूचियों का उपयोग करने से बहुत तेज़ है।

file_size = int.from_bytes(fin.read(2), byteorder='big') 

नोट इस समारोह संख्या big- या थोड़ा-endian प्रारूप में इनकोडिंग हो यह तय करने की आवश्यकता है कि:

+0

अच्छा बिंदु। लेकिन यह समाधान स्ट्रक्चर मॉड्यूल की तरह लचीला नहीं है, क्योंकि सभी तत्व value.read() के माध्यम से पढ़ते हैं, लंबे पूर्णांक होना चाहिए (यह एक लंबे पूर्णांक, बाइट, और उसके बाद एक लंबा पूर्णांक पढ़ने के लिए सुविधाजनक नहीं है, सरणी मॉड्यूल)। – EOL

+0

मैं सहमत हूं। 'सरणी' एक बाइनरी फ़ाइल को पढ़ने का एक प्रभावी तरीका है, लेकिन जब आप सही तरीके से उल्लेख करते हैं, तो हमें संरचना से निपटने के लिए बहुत लचीला नहीं होता है। –

+1

array.read को array.fromfile के पक्ष में बहिष्कृत किया गया है 1.51 –

31

एक का उपयोग कर सकते एक पूर्णांक में खोल दे, तो struct सिवाय कि

import struct 
fin = open("hi.bmp", "rb") 
firm = fin.read(2) 
file_size, = struct.unpack("i",fin.read(4)) 
+5

फ़ाइल खोलने को छोड़ा जा सकता है: 'a = np.fromfile ('file.bin', dtype = np.uint32)' – MathieuS

2

अजगर 3.2+ के रूप में, आप भी from_bytes देशी पूर्णांक पद्धति का उपयोग करके ऐसा कर सकते हैं , इसलिए आपको यह सुनिश्चित करने के लिए एंडियन-नेस निर्धारित करना होगा कि यह सही तरीके से काम करता है।