2016-02-17 2 views
8

पर फ़ाइल पढ़ें मैं X12 ईडीआई फ़ाइलों को संसाधित करने के लिए एक स्क्रिप्ट लिख रहा हूं, जिसे मैं लाइन-दर-रेखा को पुन: चालू करना चाहता हूं। फाइलें अलग-अलग अभिलेखों के अनुक्रम से बनी हैं, प्रत्येक को एक विशेष चरित्र द्वारा समाप्त किया गया है (उदा। ~, लेकिन नीचे देखें)। फाइलें बड़ी हो सकती हैं (> 100 एमबी), इसलिए मैं पूरी चीज़ को पढ़ना और विभाजित नहीं करना चाहता हूं। रिकॉर्ड न्यूलाइन से अलग नहीं हैं; पहली पंक्ति में पढ़ने से शायद पूरी फाइल पढ़ी जाएगी। फाइलें सभी ASCII हैं।एक वर्ण

पायथन स्पष्ट रूप से एक निश्चित चरित्र तक फ़ाइल पढ़ने के लिए प्रदान करता है, बशर्ते वह चरित्र एक नई रेखा है। मैं एक मनमाना चरित्र के साथ एक ही काम करना चाहता हूँ। मुझे लगता है कि लाइन द्वारा पढ़ना बफरिंग के माध्यम से लागू किया जाता है। मैं अपने स्वयं के बफर किए गए पाठक को कार्यान्वित कर सकता हूं, लेकिन बेहतर समाधान होने पर मैं अतिरिक्त कोड और ओवरहेड से बचूंगा।

नोट: मैंने कुछ समान प्रश्न देखे हैं, लेकिन वे सभी निष्कर्ष निकालने लगते हैं कि किसी को लाइन में फ़ाइल को पढ़ना चाहिए, मान लीजिए कि रेखाएं उचित आकार होंगी। इस मामले में, पूरी फाइल शायद एक पंक्ति होगी।

संपादित करें: सेगमेंट टर्मिनेटर कैरेक्टर जो भी फाइल का 106 वां बाइट है। स्क्रिप्ट लागू होने से पहले यह ज्ञात नहीं है।

tr '~' '\n' < source.txt | my-script.py 

फिर readline() उपयोग करते हैं, readlines(), या for line in file_object: के रूप में उपयुक्त:

+3

शायद फ़ाइल पॉइंटर पर '.read (some_reasonable_number)' का उपयोग करें और जब तक आप अपना '~' नहीं पाते, तब तक परिणाम के माध्यम से खोज करें, और यदि आप करते हैं, तो '.seek()' पीछे की ओर? – L3viathan

+0

मेरा मानना ​​है कि आप buffered पाठक के बारे में सही हैं, और दुर्भाग्यवश 'ओपन' में 'newline' तर्क' ~ 'की अनुमति नहीं देता है। –

+2

मुझे डर है कि आपको एक io.BytesIO पर एक समर्पित कार्यान्वयन लिखना होगा, भाग में फ़ाइल पढ़ना होगा और वापस * लाइन * भेजना आपके साथ विशेष डेलीमीटर ... –

उत्तर

2

यह अभी भी इष्टतम से दूर है अनुकूल नहीं है, लेकिन यह एक बहुत ही सरल बफर का एक शुद्ध-अजगर कार्यान्वयन होगा:

def my_open(filename, char): 
    with open(filename) as f: 
     old_fb="" 
     for file_buffer in iter(lambda: f.read(1024), ''): 
      if old_fb: 
       file_buffer = old_fb + file_buffer 
      pos = file_buffer.find(char) 
      while pos != -1 and file_buffer: 
       yield file_buffer[:pos] 
       file_buffer = file_buffer[pos+1:] 
       pos = file_buffer.find(char) 
      old_fb = file_buffer 
     yield old_fb 

# Usage: 
for line in my_open("weirdfile", "~"): 
    print(line) 
4

यदि फ़ाइल के साथ शुरू करने के लिए, अपने अजगर स्क्रिप्ट में यह पाइप से पहले फ़ाइल को बदलने, जैसे में नई-पंक्तियों होने के लिए नहीं जा रहे हैं ।

+1

और यदि प्रोग्राम कमांड लाइन से फ़ाइल लेता है , stdin नहीं, कम से कम बाश में आप प्रक्रिया प्रतिस्थापन का उपयोग कर सकते हैं: 'my-script.py <(tr' ~ '' \ n ' ShadowRanger

+0

सेगमेंट टर्मिनेटर स्क्रिप्ट आमंत्रण समय पर ज्ञात नहीं है। मैंने मूल प्रश्न स्पष्ट किया है। इसके अलावा, यह स्क्रिप्ट एक विंडोज वातावरण में चलाया जाएगा, मैं बहुत परिचित नहीं हूं, इसलिए मानक यूनिक्स उपकरण उपलब्ध नहीं हो सकते हैं। साथ ही, क्या प्रतिस्थापन प्रतिस्थापन प्रभावी ढंग से पूरी फ़ाइल सामग्री को बफर में नहीं रखेगा, अगर पाइथन स्क्रिप्ट ने इसे पर्याप्त रूप से पर्याप्त नहीं पढ़ा है? –

0

हो सकता है कि आप की तरह इस

चेतावनी कुछ चाहिए: कोड

class File(object): 

    def __init__(self, f): 
     self.file = f 

    def readline(self, delimiter='~'): 
     buffer = '' 
     while True: 
      b = self.file.read(1) 
      buffer += b 
      if b: 
       if b == delimiter: 
        yield buffer 
        buffer = '' 
      else: 
       yield buffer 
       break 
संबंधित मुद्दे