2014-06-28 5 views
9

मेरे पास file ऑब्जेक्ट है जो सार्वभौमिक मोड में खुला हो सकता है या नहीं भी हो सकता है। (यदि यह मदद करता है तो मैं file.mode के साथ इस मोड तक पहुंच सकता हूं)।सार्वभौमिक मोड में हो सकता है कि फ़ाइल स्ट्रीम पर io primitives (तलाश, पढ़ा) का उपयोग कैसे करें?

मैं मानक io विधियों का उपयोग करके इस फ़ाइल से निपटना चाहता हूं: read और seek

अगर मैं गैर सार्वभौमिक मोड में फ़ाइल खोलते हैं, सब कुछ अच्छी तरह से काम करता है:

In [1]: f = open('example', 'r') 

In [2]: f.read() 
Out[2]: 'Line1\r\nLine2\r\n' # uhoh, this file has carriage returns 

In [3]: f.seek(0) 

In [4]: f.read(8) 
Out[4]: 'Line1\r\nL' 

In [5]: f.seek(-8, 1) 

In [6]: f.read(8) 
Out[6]: 'Line1\r\nL' # as expected, this is the same as before 

In [7]: f.close() 

हालांकि, अगर मैं सार्वभौमिक मोड में फ़ाइल को खोलने के लिए, हम एक समस्या है:

In [8]: f = open('example', 'rU') 

In [9]: f.read() 
Out[9]: 'Line1\nLine2\n' # no carriage returns - thanks, 'U'! 

In [10]: f.seek(0) 

In [11]: f.read(8) 
Out[11]: 'Line1\nLi' 

In [12]: f.seek(-8, 1) 

In [13]: f.read(8) 
Out[13]: 'ine1\nLin' # NOT the same output, as what we read as '\n' was *2* bytes 

अजगर \r\n को \n के रूप में व्याख्या करता है, और लंबाई की एक स्ट्रिंग देता है 8.

हालांकि, इस स्ट्रिंग को पढ़ने में शामिल है फ़ाइल से 9 बाइट

नतीजतन, seek का उपयोग करते हुए, हम वापस नहीं आते हैं, जहां हम शुरू करते हैं, हम वापस नहीं आते हैं!


क्या यह पहचानने का कोई तरीका है कि हमने 2-बाइट न्यूलाइन का उपभोग किया है या बेहतर, इस व्यवहार को अक्षम कर दिया है?

सबसे अच्छा मैं साथ में पल पहले और पढ़ने के बाद एक tell करना है ऊपर आ सकता है, और जांच कितना हम वास्तव में मिला, लेकिन वह अविश्वसनीय रूप से असजीला लगता है।


एक अलग रूप में के रूप में, मुझे लगता है कि इस व्यवहार वास्तव में read के प्रलेखन के विपरीत है:

In [54]: f.read? 
Type:  builtin_function_or_method 
String Form:<built-in method read of file object at 0x1a35f60> 
Docstring: 
read([size]) -> read at most size bytes, returned as a string. 

If the size argument is negative or omitted, read until EOF is reached. 
Notice that when in non-blocking mode, less data than what was requested 
may be returned, even if no size parameter was given. 
मेरे पढ़ने के लिए

, कि पता चलता है कि सबसे आकार बाइट्स पर होना चाहिए पढ़ , वापस नहीं आया।

विशेष रूप से, मुझे विश्वास है कि ऊपर के उदाहरण का सही अर्थ विज्ञान होना चाहिए:

In [11]: f.read(8) 
Out[11]: 'Line1\nL' # return a string of length *7* 

एम आई प्रलेखन गलतफहमी?

+2

पाठ मोड मैं/हे शैतान द्वारा बनाया गया था मानव जाति की योजनाओं को विफल करने के लिए। प्लेग की तरह इसे से बचें। – user3553031

+1

आप जो पूछते हैं वह संभव नहीं है। फ़ाइल को बाइनरी मोड में खोलें और उसके साथ काम करें। या का उपयोग 'io.open (..., न्यू लाइन = '\ n')' सार्वभौमिक नई-पंक्तियों को निष्क्रिय करने के। – Bakuriu

उत्तर

0

मैं यहां एक उत्तर में एक कामकाज सूचीबद्ध कर रहा हूं, हालांकि मैं संतुष्ट नहीं हूं।

यह देखते हुए कि मूल समस्या सार्वभौमिक मोड में एक \n की लंबाई के बीच विसंगति, और बाइट की संख्या यह वास्तव में फ़ाइल में प्रतिनिधित्व करता है, एक ही रास्ता त्रुटि से बचने के लिए एक मध्यवर्ती स्ट्रीम से पढ़ने का है जो \n के लिए

def wrap_stream(f): 
    # if this stream is a file, it's possible to just throw the contents in 
    # another stream 
    # alternatively, we could implement an io object which used a generator to 
    # read lines from f and interpose newlines as required 
    return StringIO(f.read()) 

नई io वस्तु wrap_stream से लौटे \n के रूप में नई-पंक्तियों में दिखाई देंगे, कोई बात नहीं क्या मोड फ़ाइल में खोला गया था: वास्तव में एक बाइट का प्रतिनिधित्व करता है।

1

आप वास्तव में क्या करने की कोशिश कर रहे हैं?

आगे पढ़ने और फिर पीछे की ओर की मांग के लिए अपने कारण है कि आप, फ़ाइल में एक खास बिंदु पर लौटने के लिए तो() दर्ज करने के लिए बताएं कि आप कहां हैं का उपयोग करना चाहते है। आप कितने बाइट्स पढ़ते हैं इसका ट्रैक रखने से यह आसान है।

savepos = f.tell() 
f.read(8) 
f.seek(savepos) 
f.read(8) 
0

यह मौजूदा वर्णनकर्ता पर एक नई फ़ाइल वस्तु पाने के लिए fdopen उपयोग करने के लिए स्वीकार्य होगा, लेकिन हमलावर 'U' मोड, और बिना उपयोग करें कि प्राप्त करने के लिए? उदाहरण के लिए:

>>> import os 
>>> f=open('example','rU') 
>>> f.read() 
'Line1\nLine2\n' 
>>> ff=os.fdopen(f.fileno(),'r') 
>>> ff.seek(0) 
>>> ff.read() 
'Line1\r\nLine2\r\n' 
>>> ff.seek(-7,1) 
>>> f.read() 
'Line2\n' 
>>> 

तो तुम फ़ाइल जो कुछ भी मोड इसे बंद और उस मोड में इसे फिर से खोलने के बिना आप के लिए काम करता है हो सकता है।

संबंधित मुद्दे