अजगर के साथ एक द्विआधारी फ़ाइल पढ़ना


104

मुझे पायथन के साथ विशेष रूप से कठिन बाइनरी फ़ाइल पढ़ना मुश्किल है। क्या आप मेरी मदद कर सकते हैं? मुझे इस फ़ाइल को पढ़ने की आवश्यकता है, जिसे फोरट्रान 90 में आसानी से पढ़ा जा सकता है

int*4 n_particles, n_groups
real*4 group_id(n_particles)
read (*) n_particles, n_groups
read (*) (group_id(j),j=1,n_particles)

विस्तार से, फ़ाइल प्रारूप है:

Bytes 1-4 -- The integer 8.
Bytes 5-8 -- The number of particles, N.
Bytes 9-12 -- The number of groups.
Bytes 13-16 -- The integer 8.
Bytes 17-20 -- The integer 4*N.
Next many bytes -- The group ID numbers for all the particles.
Last 4 bytes -- The integer 4*N. 

मैं इसे पायथन के साथ कैसे पढ़ सकता हूं? मैंने सब कुछ करने की कोशिश की लेकिन यह कभी काम नहीं आया। क्या कोई मौका है जो मैं अजगर में एक f90 प्रोग्राम का उपयोग कर सकता हूं, इस बाइनरी फ़ाइल को पढ़ रहा हूं और फिर उस डेटा को सहेज सकता हूं जिसे मुझे उपयोग करने की आवश्यकता है?


1
क्या यह फाइल फोरट्रान प्रोग्राम द्वारा लिखी गई थी? यदि ऐसा है, तो यह कैसे लिखा गया था, क्योंकि फोरट्रान, डिफ़ॉल्ट रूप से, प्रत्येक रिकॉर्ड को फाइल करने के लिए लिखने से पहले अतिरिक्त डेटा जोड़ता है। डेटा पढ़ते समय आपको इसका ध्यान रखना पड़ सकता है।
क्रिस

1
कृपया मेरी पिछली टिप्पणी को अनदेखा करें, अंतर 8 और 4 * एन स्पष्ट रूप से यह अतिरिक्त डेटा हैं।
क्रिस

2
इसके अलावा, अजगर में बाइनरी फ़ाइल पढ़ने वाले प्रश्न के उत्तर देखें ।
क्रिस

Numpy का fromfileकार्य बाइनरी फ़ाइलों को पढ़ना आसान बनाता है। मेरा यही सुझाव है।
छोटू

... और हमेशा अपने एंडियन-नेस, एस्प के लिए बाहर देखो। जब विभिन्न निर्माता के कंप्यूटरों के बीच पोर्टिंग होती है।
ड्रैगनलैड

जवाबों:


155

बाइनरी फ़ाइल सामग्री को इस तरह पढ़ें:

with open(fileName, mode='rb') as file: # b is important -> binary
    fileContent = file.read()

फिर "अनपैक" बाइनरी डेटा का उपयोग कर struct.unpack :

प्रारंभ बाइट्स: struct.unpack("iiiii", fileContent[:20])

शरीर: शीर्षक बाइट्स और अनुगामी बाइट (= 24) को अनदेखा करें; शेष भाग शरीर बनाता है, यह जानने के लिए कि शरीर में बाइट्स की संख्या 4 से पूर्णांक विभाजन है; 'i'अनपैक पद्धति के लिए सही प्रारूप बनाने के लिए प्राप्त भागफल को स्ट्रिंग द्वारा गुणा किया जाता है :

struct.unpack("i" * ((len(fileContent) -24) // 4), fileContent[20:-4])

अंत बाइट: struct.unpack("i", fileContent[-4:])


क्या आप कृपया इस अन्य पोस्ट को देख सकते हैं? stackoverflow.com/questions/8092469/… ... मैं फिर से एक और द्विआधारी फ़ाइल पढ़ने के लिए हूँ, लेकिन इस मामले में मैं विवरण में बाइट संरचना को नहीं जानता। उदाहरण के लिए, मुझे पता चला कि कभी-कभी पूर्णांक होता है। हालांकि, आईडीएल के साथ यह डेटा पढ़ना वास्तव में सरल है। क्या मैं अजगर के साथ भी ऐसा ही कर सकता हूं?
ब्रायन

कृपया संकेत दें (अन्य पोस्ट के अंदर, यहां नहीं) आप पोस्ट किए गए उत्तरों और टिप्पणियों से खुश क्यों नहीं हैं। शायद आपको अधिक विवरण प्रदान करने के लिए प्रश्न को अपडेट करना चाहिए ... अपडेट होने पर मैं इस पर एक नज़र डालूंगा।
gecco

इस उत्तर को देखें यदि आपको एक अनपैक्ड चार [] को स्ट्रिंग में बदलने की आवश्यकता है।
पीटरएम

import struct
JW

23

सामान्य तौर पर, मैं आपको सलाह दूंगा कि आप इसके लिए पायथन के स्ट्रक्चर मॉड्यूल का उपयोग करें। यह पायथन के साथ मानक है, और आपके प्रश्न के विनिर्देश का प्रारूपण स्ट्रिंग के लिए उपयुक्त में अनुवाद करना आसान होना चाहिए struct.unpack()

ध्यान दें कि यदि खेतों के बीच / आसपास "अदृश्य" पैडिंग है, तो आपको यह पता लगाना होगा कि इसे unpack()कॉल में शामिल करना है , या आप गलत बिट्स को पढ़ेंगे।

फ़ाइल की सामग्री को अनपैक करने के लिए कुछ को पढ़ना बहुत तुच्छ है:

import struct

data = open("from_fortran.bin", "rb").read()

(eight, N) = struct.unpack("@II", data)

यह पहले दो क्षेत्रों को अनपैक करता है, यह मानते हुए कि वे फ़ाइल की शुरुआत में शुरू करते हैं (कोई पैडिंग या एक्सट्रांस डेटा नहीं), और देशी बाइट-ऑर्डर ( @प्रतीक) भी ग्रहण करते हैं । Iस्वरूपण स्ट्रिंग में s ", अहस्ताक्षरित पूर्णांक 32 बिट" मतलब है।


ठीक है, लेकिन मुझे यह भी नहीं पता कि फाइल के बाइट्स को कैसे पढ़ना है। अपने प्रश्न से मैं बाइट्स 5 से 8 तक फ़ाइल कैसे पढ़ सकता हूं और फिर परिणाम को पूर्णांक में बदल सकता हूं? क्षमा करें, लेकिन मैं पायथन के साथ नया हूं।
ब्रायन

14

आप उपयोग कर सकते हैं numpy.fromfile, जो पाठ और बाइनरी फ़ाइलों दोनों से डेटा पढ़ सकते हैं। आप पहले एक डेटा प्रकार का निर्माण करेंगे, जो आपके फ़ाइल प्रारूप का प्रतिनिधित्व करता है, का उपयोग करते हुए numpy.dtype, और फिर फ़ाइल का उपयोग करके इस प्रकार को पढ़ें numpy.fromfile


2
यह याद करने के लिए आसान! डॉक्स थोड़े पतले हैं; कुछ चर्चा के लिए reddit.com/r/Python/comments/19q8nt/… देखें
खो दिया '

11

किसी bytesवस्तु को बाइनरी फ़ाइल पढ़ने के लिए :

from pathlib import Path
data = Path('/path/to/file').read_bytes()  # Python 3.5+

intडेटा के 0-3 से एक बनाने के लिए:

i = int.from_bytes(data[:4], byteorder='little', signed=False)

intडेटा से कई एस अनपैक करने के लिए :

import struct
ints = struct.unpack('iiii', data[:16])

0

जब मुझे बाइनरी फ़ाइलों को पढ़ने और लिखने की बात आती है, तो मुझे पायथन की कमी महसूस हुई, इसलिए मैंने एक छोटा मॉड्यूल (पायथन 3.6+ के लिए) लिखा।

बाइनरीफाइल के साथ आप ऐसा कुछ करेंगे (मैं अनुमान लगा रहा हूं, क्योंकि मुझे फोरट्रान नहीं पता है):

import binaryfile

def particle_file(f):
    f.array('group_ids')  # Declare group_ids to be an array (so we can use it in a loop)
    f.skip(4)  # Bytes 1-4
    num_particles = f.count('num_particles', 'group_ids', 4)  # Bytes 5-8
    f.int('num_groups', 4)  # Bytes 9-12
    f.skip(8)  # Bytes 13-20
    for i in range(num_particles):
        f.struct('group_ids', '>f')  # 4 bytes x num_particles
    f.skip(4)

with open('myfile.bin', 'rb') as fh:
    result = binaryfile.read(fh, particle_file)
print(result)

जो इस तरह एक उत्पादन का उत्पादन करता है:

{
    'group_ids': [(1.0,), (0.0,), (2.0,), (0.0,), (1.0,)],
    '__skipped': [b'\x00\x00\x00\x08', b'\x00\x00\x00\x08\x00\x00\x00\x14', b'\x00\x00\x00\x14'],
    'num_particles': 5,
    'num_groups': 3
}

फोरट्रान के अतिरिक्त डेटा को स्किप करने के लिए मैंने स्किप () का उपयोग किया, लेकिन आप फ़ोर्टन रिकॉर्ड को ठीक से हैंडल करने के लिए एक उपयोगिता जोड़ना चाहें। यदि आप करते हैं, तो एक पुल अनुरोध का स्वागत किया जाएगा।


-2
import pickle
f=open("filename.dat","rb")
try:
    while True:
        x=pickle.load(f)
        print x
except EOFError:
    pass
f.close()

7
शायद इस बात का थोड़ा स्पष्टीकरण के लायक है कि यह अन्य उत्तरों की तुलना में बेहतर क्यों है (या कम से कम जितना अच्छा है)।
फिल

2
क्या आपने फोरट्रान जनित बाइनरी के साथ इस काम को सत्यापित किया है?
एजेंटप

1
और यह भी बताएं कि यह क्या करता है ... अचार क्या है? क्या pickle.loadलोड करता है? क्या यह एक फोरट्रान स्ट्रीम, प्रत्यक्ष या अनुक्रमिक फ़ाइलों को लोड करता है? वे अलग हैं और संगत नहीं हैं।
व्लादिमीर एफ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.