2012-03-10 21 views
38

解析'r'模式中的文本文件比在rb模式下解析文本文件更方便嗎? 特別是當有問題的文本文件可能包含非ASCII字符時。在r和rb模式下解析文本文件的區別

+0

您正在閱讀文本文件還是二進制文件? – 2012-03-10 05:15:12

+0

一個文本文件。但無論出於何種原因,我都將該文件作爲字節流。 – MxyL 2012-03-10 05:16:51

回答

44

這取決於您正在使用的Python版本。在Python 2中,Chris Drappier's answer適用。在Python 3中,它是一個不同的(也是更一致的)故事:在文本模式('r')中,Python將根據你給它的文本編碼解析文件(或者,如果你不給它,平臺相關的默認值),而read()會給你一個str。在二進制('rb')模式下,Python不會假定該文件包含可合理解析爲字符的東西,並且read()爲您提供了一個bytes對象。

此外,在Python 3,通用換行符('\n'和特定於平臺的換行符公約之間的翻譯,所以你不必關心他們)是可用於文本模式的文件上任何平臺,而不僅僅是視窗。

+0

,會在文本模式下自動嘗試檢測它是什麼類型的編碼?我想象不得不檢測編碼對於字節對象來說是一個相當大的挑戰。 – MxyL 2012-03-10 06:47:47

+1

@Keikoku無需任何元數據即可獨自檢測基於數據流的編碼,這是不可能的 - 考慮ASCII +的各種編碼使用第8位信息而不是奇偶校驗;它們都共享255個有效的單字節序列,但其中只有一半(ASCII半字節)表示每個序列中的相同字符。 Python的默認不會猜測它,它是一個會話範圍的默認編碼,拼寫爲'sys.getdefaultencoding()'。在我的Py3安裝上,它的UTF-8,但你不能依賴於那種情況。 – lvc 2012-03-10 07:26:44

19

documentation

在Windows中, 'B' 附加到模式以二進制方式打開文件,所以也有模式,如 'RB', 'WB' 和「R + B 」。 Windows上的Python區分了文本和二進制文件;在讀取或寫入數據時,文本文件中的行尾字符會自動稍作修改。這種對文件數據的後臺修改對於ASCII文本文件來說很好,但它會破壞像JPEG或EXE文件中的二進制數據。在讀寫這些文件時要非常小心地使用二進制模式。在Unix上,向模式附加'b'並不會造成什麼影響,所以您可以在所有二進制文件中獨立使用它。

+0

因此,基本上試圖讀取二進制模式下的行要困難得多,因爲我不能保證EOL字符是\ n還是\ r \ n或其他東西?對於py3, – MxyL 2012-03-10 05:47:29

8

區別在於如何處理行尾(EOL)。不同的操作系統在Unix中使用不同的字符來標記EOL - \n,在OS X之前的Mac版本中使用\r,在Windows中使用\r\n。當以文本模式打開文件時,讀取文件時,Python將用\n替換從文件中讀取的操作系統特定的行尾字符。反之亦然,即當您嘗試將\n寫入以文本模式打開的文件時,它將編寫OS特定的EOL字符。你可以通過檢查os.linesep找到你的操作系統默認的EOL。

當以二進制模式打開文件時,不會發生映射。你讀的是你得到的。請記住,文本模式是默認模式。因此,如果您正在處理非文本文件(圖像,視頻等),請確保以二進制模式打開文件,否則最終會通過引入(或刪除)一些字節來搞亂文件。

Python也有一個通用的換行模式。當在此模式下打開文件時,Python會將所有字符\r,\n\r\n映射到\n

+0

Python 2和Python 3都適用嗎? – Agostino 2016-11-21 22:38:37

2

澄清和回答Agostino's comment/question(我沒有足夠的信譽評論這樣忍耐一下,說明這是一個答案...):

在Python 2沒有行結束脩改情況,無論是在文字也不是二進制模式 - 如前所述,在Python 2 Chris Drappier's answer適用(請注意,其現在的鏈接指向3。X Python文檔,但克里斯的引用文本當然是從Python 2 input and output tutorial

所以,不,這是誠然,在文本模式與Python 2 在非Windows打開文件做任何行結束脩改:

0 $ cat data.txt 
line1 
line2 
line3 
0 $ file data.txt 
data.txt: ASCII text, with CRLF line terminators 
0 $ python2.7 -c 'f = open("data.txt"); print f.readlines()' 
['line1\r\n', 'line2\r\n', 'line3\r\n'] 
0 $ python2.7 -c 'f = open("data.txt", "r"); print f.readlines()' 
['line1\r\n', 'line2\r\n', 'line3\r\n'] 
0 $ python2.7 -c 'f = open("data.txt", "rb"); print f.readlines()' 

然而,可以以打開通用換行符模式文件在Python 2,其不正是執行所述線路端MOD:

0 $ python2.7 -c 'f = open("data.txt", "rU"); print f.readlines()' 
['line1\n', 'line2\n', 'line3\n'] 

(通用換行模式說明被棄用的Python 3.X的)

在Python 3中,在另一方面,特定於平臺的行結束做得到歸爲「\ n」閱讀文本文件時模式,並且當以文本模式寫入時(除了字節<-> unicode <->字節解碼/編碼在文本模式下進行),'\ n'被轉換爲當前平臺的默認行結束。例如。在Linux上讀取Dos/Win CRLF行結束的文件會將行結束標準化爲'\ n'。

+0

Python3的開放函數有一個換行參數來控制如果需要 https://docs.python.org/3/library/functions.html#open 「換行符控制通用換行符模式的工作方式(它僅適用於文本它可以是None,'','\ n','\ r'和'\ r \ n'。它的工作原理如下:當從流中讀取輸入時,如果換行符爲None,通用換行符模式爲啓用」 – Davos 2017-09-23 13:27:25