2014-08-27 46 views
2

我在Windows 7 64位上使用WinPython 2.7。Python 2.7:len()從換行符返回文件行的錯誤值

我想打開一個文件,逐行讀取它的內容,當遇到特定的序列時,我想繼續操作文件內容。

要保存當前位置,我將當前行的長度附加到行長度列表中。但是,len(line)返回的值太小了1.我懷疑這是由於Windows的換行符\r\n

考慮以下代碼爲例。

  • TESTFILE.TXT:

    Line1 
    Line2 
    Line3 
    
  • test.py

    fn = 'testfile.txt' 
    
    f = open(fn) 
    
    line_offsets = [] 
    for line in f: 
        line_offsets.append(len(line)) 
    
    f.seek(line_offsets[1]) 
    print '%r' % f.read() 
    
  • 輸出:

    '\nLine2\nLine3' 
    
  • 預期輸出:

    'Line2\nLine3' 
    

我試圖通過指定的讀法(用通用換行符)打開文件:f = open(fn, 'rU') 但這並沒有這樣的伎倆無論是。如果我以二進制模式打開文件,我可以使它工作,但這實際上是一個文本文件,而不是二進制文件,所以我想避免這種情況,我也想了解這裏發生了什麼。

回答

4

以二進制模式打開文件,並且'\r'不會從行中剝離。然後len將返回適當的字節數。

f = open(fn, 'rb') 

這將是,如果你的端口到Python 3尤爲重要,因爲非二進制文件將在您閱讀和計數可能是方式關閉字節解碼成Unicode字符。

+0

事實上,在Python 3中,你應該只能以相當有限的方式在文本文件中搜索。從教程中:'在文本文件(在模式字符串中沒有ab的情況下打開的文件)中,只允許相對於文件的開頭尋找(例外情況是以seek(0,2)尋找文件末尾),而只有有效的偏移值是從f.tell()返回的值,或者是零。任何其他偏移值都會產生未定義的行爲。' – Blckknght 2014-08-27 17:22:40

+0

好吧,所以使用二進制模式似乎是我的方式。但爲什麼它不適用於'RU'?是不是通用的換行模式應該處理這種東西? – Vertho 2014-08-28 16:36:53

+0

@Vertho通用換行符在讀取時會明確地轉換爲'\ n',所以如果文件包含'\ r \ n'作爲兩個字符,那麼您的字符串將只包含'\ n' - 它根本無助於您的問題。即使在文本模式下打開文件,seek也始終以二進制模式工作。 – 2014-08-28 16:51:24

0

您可以使用splitlines()從文件中刪除這些行。它根據documentation對各種換行符具有容差。

0

爲了獲得您想要的行爲,您可以在讀取每行之前明確地調用f.tell(),然後使用f.readline()來讀取該行。由於Windows issue with tell(),您可能還必須以二進制模式工作,並自行處理任何行結束問題。使用該文件作爲迭代器將無法正常工作,因爲它會被緩衝,並且可能會使文件指針超出您在文件中讀取的行。

>>> with open('testfile.txt', 'rb') as f: 
...  while True: 
...   here = f.tell() 
...   line = f.readline() 
...   if not line: 
...    break 
...   print('%02d\t%r' % (here, line)) 
... 
00 'Line1\n' 
06 'Line2\n' 
12 'Line3\n' 
+0

有沒有保證'f.readline'不會緩衝? - 我可以很容易地看到這在不同的python實現/版本上打破... – mgilson 2014-08-27 18:06:46

+0

不,但它適用於CPython 2/3和PyPy。我希望其他實現可以在這裏遵守事實上的標準行爲。 – 2014-08-27 20:22:24