Qual è l'ultimo carattere di un file?


19

Ho appena letto le risposte a "Rimozione di un carattere di nuova riga alla fine di un file" e tutti hanno detto di eliminare l'ultimo carattere. La mia domanda è: non è l'ultimo personaggio?



1
@SorenBjornstad Vorrei anche aggiungere che quando c'è una nuova riga alla fine di un file di testo Unix, è lì perché termina l'ultima riga. Un file di testo vuoto non ha una nuova riga alla fine: è una sequenza di zero caratteri.
Kaz,

3
Per essere un po 'pedanti, CPM e DOS hanno usato ^ Z come carattere EOF, e talvolta potresti ancora incontrare file che terminano con ^ Z.
Edward Falk,

Risposte:


13

Un file non termina con un carattere Fine file, come indicato correttamente nelle risposte precedenti. Ma penso che le risposte e i commenti contengano alcune inesattezze che vale la pena sottolineare:

  • Il set di caratteri ASCII non contiene un carattere EOF esatto. Esistono diversi caratteri di controllo "fine": Fine testo (3), Fine trasmissione (4), Blocco fine trasmissione (23), Fine supporto (25). File Separator (28) forse si avvicina di più a un personaggio EOF. Il codice 26 è "Sostituto", non EOF.

  • Ctrl- Dè associato solo con l'ingresso terminale. Ad esempio il comando cat filea fileb filec > outfilenon comporta Ctrl- D. A proposito, puoi cambiare il carattere EOF terminale in qualcosa di diverso da Ctrl- Dusando il sttycomando.

  • A rigor di termini, Ctrl- D(o qualunque cosa tu abbia cambiato) non è un codice chiave EOF. Ciò che fa è fare in modo che la readchiamata di sistema ritorni con quale input è disponibile, proprio come premendo return fa sì che la chiamata di sistema letta ritorni una linea di caratteri al chiamante. Per convenzione un valore di ritorno pari a zero dalla chiamata di sistema letta (ovvero zero caratteri letti) segnala la fine della condizione del file. Tuttavia, il file di input non viene chiuso automaticamente e, se l'input proviene dal terminale, non viene messo in uno stato di "fine del file". È possibile scrivere un programma che continua a leggere dal terminale anche dopo una "fine del file" e la chiamata in lettura può restituire un valore diverso da zero per la riga di input successiva.

  • L'analogia tra i caratteri eof ed eol può essere vista se Ctrl- Dviene premuto quando alcuni input sono già stati scritti sulla riga. Ad esempio, se si scrive "abc" e si preme Ctrl, Dla chiamata di lettura ritorna, questa volta con un valore di ritorno di 3 e con "abc" memorizzato nel buffer passato come argomento. Poiché read non restituisce 0, questo non è interpretato come una condizione EOF dalla convenzione precedente. Allo stesso modo, premendo return per rendere la chiamata in lettura ritorna con l'intera linea di input (inclusa la nuova riga). Puoi provarlo con il catcomando: scrivi alcuni caratteri sulla riga e premi Ctrl- D. Vedrai i personaggi echeggiati di nuovo in catattesa di ulteriori input.

  • Tutto quanto sopra si applica solo quando il terminale è in modalità "cotto", a differenza della modalità "crudo", in cui l'elaborazione dell'input di linea è ridotta al minimo. In modalità raw, un carattere Ctrl-D viene effettivamente consegnato al buffer di input.


19

I caratteri di controllo ASCII hanno definizioni degli anni '60 (che in realtà precedono quello che potresti considerare una rete ). Non tutti quei personaggi di controllo sono usati nel modo in cui erano stati definiti per le apparecchiature di telecomunicazione di allora.

Su sistemi simili a Unix, non è necessario un EOFpersonaggio; nessuno è usato. Il sistema può dire alle applicazioni quanti byte ci sono in un file:

  • Su alcuni altri sistemi (visti in VMS, DOS, Windows), un control-Z può fungere da marker di fine file perché nelle versioni precedenti il sistema non è in grado di dire ad alcune applicazioni quanti byte ci sono nel file.

    Nel caso di VMS, la limitazione era dovuta al modo in cui il runtime C funzionava. Le applicazioni in linguaggio assembly potrebbero (e hanno) ottenuto la dimensione corretta del file.

  • I sistemi Unix nella shell usano convenzionalmente control-D per dire a un'applicazione che è stata raggiunta la fine dell'input (file), ma control-D non è memorizzato nel file.

In C, EOFè fatto apposta -1per indicare che non è un carattere valido. L'I / O standard ritorna EOFquando viene rilevata una condizione di fine file, non un carattere speciale.

A proposito, i file non devono necessariamente terminare con un carattere di nuova riga (avanzamento di riga ASCII). Gli editor di testo possono far fronte a file che sono tutti testo stampabile ma privi di una nuova riga finale.


8
POSIX definisce un file di testo come un file contenente una sequenza di righe e, a sua volta, ciascuna riga è una sequenza di caratteri non di nuova riga seguita da una nuova riga. Quindi un file che termina con qualcosa tranne 0x0A non è un file di testo conforme.
Damian Yerrick,

2
Ne sono consapevole, motivo per cui ho sottolineato che gli editor di testo funzionano. (I file binari non hanno questo vincolo).
Thomas Dickey,

Vale davvero la pena notare che i file destinati a essere gestiti come testo che non hanno una nuova riga finale sono ancora discutibilmente in cattive condizioni (anche se i tipici editor di testo sono stati codificati per compensare tali file), almeno se lo si desidera effettivamente ampiamente user-friendly / compatibile, perché la mancanza di una nuova riga finale può aggiungere ulteriori difficoltà in varie circostanze (concatenazione / stampa di più file di testo, analisi con strumenti tipici della riga di comando, editor minimi come quelli busyboxdi vi, ecc.).
mtraceur,

(1) Prima di VMS, RT-11 RSX-11 TOPS-10 aveva filesystem precisi solo su un blocco e aveva bisogno di un carattere EOF. Così ha fatto CP / M, che apparentemente l'ha copiato da DEC ed è stato a sua volta copiato dai primi MS-DOS e poi passato a Windows. (2) In Unix è il driver tty non la shell, come descritto in maggior dettaglio da JohanM, sebbene le persone di solito eseguano shell su dispositivi tty.
dave_thompson_085

Certo, DEC era di nuovo lì (e nota che ho menzionato le versioni precedenti ). Se fosse l' origine della funzione CP / M sarebbe un argomento interessante da esplorare (non qui); Ho citato questi casi per dare qualche informazione sulle alternative.
Thomas Dickey,

7

EOF non è un personaggio. È uno stato che indica non più caratteri da leggere da un flusso di file. Quando si immette il comando EOF dal terminale, si sta segnalando al sistema operativo di chiudere il flusso di input, senza inserire un carattere speciale.


1
Sì, ma nella tabella ASCII EOF è 26, quindi ho pensato che l'ultimo byte fosse la rappresentazione binaria di 26. Quindi, come può un programma che legge un input sapere dove finisce?
Sworwitz,

ASCII era pensato per il passaggio di informazioni su una rete. In tal caso, è necessario un carattere EOF. (ASCII aveva anche molti codici di controllo. Non tutto era stampabile.) In caso di flussi di file, la dimensione del file è già nota attraverso il file system in modo che il sistema operativo possa dire quando non ci sono più dati da leggere.
Munir,

@sworwitz: per quanto riguarda C, le funzioni di lettura dell'ingresso che restituiscono un carattere per chiamata restituiscono un int (di solito un numero a 32 bit ma deve essere almeno 16 bit) non un carattere. La funzione segnala ed EOF restituendo -1 (0xffffffff) che non è un valore valido a 8 bit, quindi non verrà confuso da alcun carattere ASCII, nemmeno 0xff. Le funzioni che restituiscono una stringa restituiscono anche la lunghezza dei dati letti. Questa lunghezza può essere utilizzata per segnalare nessun dato o fine dei dati (di nuovo, la lunghezza può essere -1). Infine, c'è anche una funzione che puoi chiamare che ti dirà se uno stream ha raggiunto la fine
slebetman

Ok grazie! Quindi quando in bash premo Ctrl + d do in input il carattere ASCII, giusto?
Sworwitz,

@sworwitz Non esattamente. Prima di bashmettere le mani sull'input, viene massaggiato dal driver TTY. Questo driver intercetta Ctrl-D e invia un EOF a bash (dove EOF non è un personaggio, ma uno stato del file speciale)
Stig Hemmer
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.