2012-03-10 10 views
38

Ciò che rende l'analisi di un file di testo in modalità 'r' più conveniente rispetto all'analisi in modalità 'rb'? Specialmente quando il file di testo in questione può contenere caratteri non ASCII.Differenza tra l'analisi di un file di testo in modalità r e rb

+0

Stai leggendo un file di testo o un file binario? –

+0

Un file di testo. Ma per qualsiasi motivo mi viene dato il file come un flusso di byte. – MxyL

risposta

44

Questo dipende un po 'dalla versione di Python che si sta utilizzando. In Python 2 vale Chris Drappier's answer.

In Python 3, è una storia diversa (e più coerente): in modalità testo ('r'), Python analizzerà il file in base alla codifica del testo che gli viene assegnata (o, se non lo si fornisce, a impostazione predefinita dalla piattaforma), e read() ti darà un str. In modalità binaria ('rb'), Python non presuppone che il file contenga cose che possono essere analizzate come caratteri, e read() fornisce un oggetto bytes.

Inoltre, in Python 3, le nuove linee universali (la traduzione tra '\n' e specifico per la piattaforma di nuova riga convenzioni in modo da non dover preoccuparsi di loro) è disponibile per i file di testo in modalità on qualsiasi piattaforma, non solo Finestre.

+0

per py3, la lettura in modalità testo cercherà automaticamente di rilevare quale tipo di codifica è? Immagino che dover rilevare la codifica sia una vera sfida con un oggetto bytes. – MxyL

+1

@Keikoku Rilevare la codifica basata su un flusso da solo, senza alcun metadata, è impossibile - pensate alle varie codifiche ASCII + usate l'ottavo bit per informazioni piuttosto che per parità; tutti condividono 255 sequenze valide di un byte, ma solo la metà di esse (la metà ASCII) rappresenta lo stesso carattere in ciascuna. L'impostazione predefinita di Python non è indovinarla, è una codifica predefinita a livello di sessione, scritta 'sys.getdefaultencoding()'. Sulla mia installazione Py3, la sua UTF-8, ma non si può fare affidamento sul fatto che sia sempre il caso. – lvc

19

dal documentation:

In Windows, 'b' aggiunto al modo si apre il file in modalità binaria, quindi non ci sono modalità anche come 'rb', 'wb', e 'r + b '. Python su Windows distingue tra testo e file binari; i caratteri di fine riga nei file di testo vengono automaticamente modificati leggermente quando i dati vengono letti o scritti. Questa modifica "dietro le quinte" dei dati dei file va bene per i file di testo ASCII, ma corrompe i dati binari come quelli nei file JPEG o EXE. Prestare molta attenzione all'utilizzo della modalità binaria durante la lettura e la scrittura di tali file. Su Unix, non fa male aggiungere una "b" alla modalità, quindi puoi utilizzarla in modo indipendente per tutti i file binari.

+0

Quindi, in sostanza, provare a leggere le righe in modalità binaria è molto più difficile perché non sono sicuro che il carattere EOL sia \ n o \ r \ n o qualcos'altro? – MxyL

8

La differenza sta nel modo in cui viene gestito il fine linea (EOL). Diversi sistemi operativi utilizzano caratteri diversi per contrassegnare EOL - \n in Unix, \r in versioni Mac precedenti a OS X, \r\n in Windows. Quando un file viene aperto in modalità testo, quando il file viene letto, Python sostituisce il carattere di fine riga specifico del sistema operativo letto dal file con solo \n. E viceversa, cioè quando provate a scrivere \n in un file aperto in modalità testo, scriverà il carattere EOL specifico del sistema operativo. Puoi trovare quale EOL predefinito del tuo sistema operativo controlla os.linesep.

Quando un file viene aperto in modalità binaria, non viene eseguita alcuna mappatura. Quello che leggi è ciò che ottieni. Ricorda, la modalità testo è la modalità predefinita. Quindi, se gestisci file non di testo (immagini, video, ecc.), Assicurati di aprire il file in modalità binaria, altrimenti finirai per incasinare il file introducendo (o rimuovendo) alcuni byte.

Python ha anche una modalità newline universale. Quando un file viene aperto in questa modalità, Python esegue il mapping di tutti i caratteri \r, \n e \r\n a \n.

+0

È vero sia per Python 2 che per Python 3? funzione open – Agostino

2

Per chiarimenti e rispondere Agostino's comment/question (non ho la reputazione sufficiente a lasciare un commento, in modo da portare con me affermando questo come una risposta ...):

In Python 2 nessuna modifica di fine linea accade, né nel testo né la modalità binaria - come è stato affermato in precedenza, in Python 2 Chris Drappier's answer si applica (si noti che il suo collegamento al giorno d'oggi punta al 3.x docs Python, ma Chris' testo citato è, naturalmente, dalla Python 2 input and output tutorial)

Quindi no, è non vero che l'apertura di un file in di testo modalità con Python 2 sulla non-Windows fa alcun fine linea modifica:

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()' 

è tuttavia possibile aprire il file in modalità newline universale in Python 2, che fa esattamente effettuare detta estremità linea mod:

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

(la modalità newline universale specificazione è deprecato come di Python 3.x)

su Python 3, d'altra parte, la linea specifico per la piattaforma estremità si ottiene normalizzato a '\ n' durante la lettura di un file in formato testo modalità, e '\ n' viene convertito alla fine della linea predefinita della piattaforma corrente quando si scrive in modalità testo (oltre ai byte < -> unicode < -> decodifica/codifica dei byte in corso in modalità testo). Per esempio. la lettura di un file Dos/Win con riga CRLF su Linux normalizzerà la fine della linea su '\ n'.

+0

di python3 ha un parametro di nuova riga per controllare che se necessario https://docs.python.org/3/library/functions.html#open "controlli di nuova riga come funziona la modalità a capo universali (si applica solo al testo modalità). Può essere None, '', '\ n', '\ r' e '\ r \ n'. Funziona come segue: Quando si legge l'input dallo stream, se newline è None, la modalità newlines universale è abilitato" – Davos

Problemi correlati