Qual é o último caractere em um arquivo?


19

Acabei de ler as respostas para "Removendo um caractere de nova linha no final de um arquivo" e todos disseram para excluir o último caractere. Minha pergunta é: o personagem eof não é o último?



11
@SorenBjornstad Eu também gostaria de acrescentar que quando há uma nova linha no final de um arquivo de texto Unix, ela existe porque termina a última linha. Um arquivo de texto vazio não possui nova linha no final: é uma sequência de zero caracteres.
Kaz

3
Para ser um pouco pedante, o CPM e o DOS usaram ^ Z como o caractere EOF, e às vezes você ainda pode encontrar arquivos que terminam com ^ Z.
Edward Falk

Respostas:


13

Um arquivo não termina com um caractere Fim do arquivo, como as respostas anteriores afirmam corretamente. Mas acho que as respostas e comentários contêm algumas imprecisões que merecem destaque:

  • O conjunto de caracteres ASCII não contém um caractere EOF exato. Existem vários caracteres de controle "final": Fim do texto (3), Fim da transmissão (4), Bloco do fim da transmissão (23), Fim do meio (25). O Separador de arquivos (28) talvez se aproxime mais de um caractere EOF. O código 26 é "Substituto", não EOF.

  • Ctrl- Destá associado apenas à entrada do terminal. Por exemplo, o comando cat filea fileb filec > outfilenão envolve Ctrl- D. A propósito, você pode alterar o caractere EOF do terminal para algo diferente de Ctrl- Dusando o sttycomando

  • A rigor, Ctrl- D(ou o que você alterou) não é um código de chave EOF. O que ele faz é fazer com que a readchamada do sistema retorne com a entrada disponível, assim como pressionar return faz com que a chamada de sistema de leitura retorne uma linha de caracteres para o chamador. Por convenção, um valor de retorno zero da chamada do sistema de leitura (ou seja, zero caracteres lidos) sinaliza uma condição de final de arquivo. No entanto, o arquivo de entrada não é fechado automaticamente e, se a entrada vier do terminal, não é colocada no estado "final do arquivo". Você pode escrever um programa que continue lendo o terminal mesmo após um "final de arquivo" e a chamada de leitura poderá retornar diferente de zero para a próxima linha de entrada.

  • A analogia entre os caracteres eof e eol pode ser vista se Ctrl- Dfor pressionado quando alguma entrada já tiver sido escrita na linha. Por exemplo, se você escrever "abc" e pressionar Ctrl- Da chamada de leitura retornará, desta vez com um valor de retorno 3 e com "abc" armazenado no buffer passado como argumento. Como a leitura não retorna 0, isso não é interpretado como uma condição EOF pela convenção acima. Da mesma forma, pressionar retorno para faz com que a chamada de leitura retorne com toda a linha de entrada (incluindo nova linha). Você pode tentar isso com o catcomando: escreva alguns caracteres na linha e pressione Ctrl- D. Você verá os caracteres ecoando de volta para você e cataguardando mais informações.

  • Tudo acima se aplica somente quando o terminal está no modo "cozido", em oposição ao modo "bruto", no qual o processamento de entrada de linha é minimizado. No modo bruto, um caractere Ctrl-D é realmente entregue ao buffer de entrada.


19

Os caracteres de controle ASCII têm definições da década de 1960 (na verdade, precedendo o que você pode considerar uma rede ). Nem todos esses caracteres de controle são usados ​​da maneira que foram definidos para equipamentos de telecomunicações naquela época.

Em sistemas tipo Unix, não há necessidade de um EOFpersonagem; nenhum é usado. O sistema pode dizer aos aplicativos quantos bytes há em um arquivo:

  • Em alguns outros sistemas (vistos no VMS, DOS, Windows), um controle-Z pode atuar como um marcador de fim de arquivo, porque em versões mais antigas o sistema não podia dizer a alguns aplicativos quantos bytes há no arquivo.

    No caso do VMS, a limitação ocorreu devido à maneira como o tempo de execução C funcionava. Os aplicativos em linguagem assembly poderiam (e conseguiram) obter o tamanho correto do arquivo.

  • Os sistemas Unix no shell usam convencionalmente control-D para informar a um aplicativo que um final de entrada (arquivo) foi atingido, mas o control-D não é armazenado no arquivo.

Em C, EOFé propositadamente feito -1para indicar que não é um caractere válido. A E / S padrão retorna EOFquando uma condição de fim de arquivo é detectada - não um caractere especial.

A propósito, os arquivos não precisam terminar com um caractere de nova linha (alimentação de linha ASCII). Os editores de texto podem lidar com arquivos que são todos textos imprimíveis, mas não possuem uma nova linha final.


8
O POSIX define um arquivo de texto como um arquivo que contém uma sequência de linhas e, por sua vez, cada linha como uma sequência de caracteres que não são de nova linha, seguidos por uma nova linha. Portanto, um arquivo que termina com algo que não seja 0x0A não é um arquivo de texto em conformidade.
Damian Yerrick

2
Estou ciente disso, razão pela qual indiquei que os editores de texto funcionam. (Arquivos binários não têm essa restrição).
Thomas Dickey

Vale a pena notar que os arquivos destinados a serem manipulados como texto que não possuem uma nova linha à direita ainda são uma forma indiscutivelmente ruim (mesmo que editores de texto típicos tenham sido codificados para compensar esses arquivos), pelo menos se você realmente deseja que ele seja amplamente amigável / compatível, porque a falta de uma nova linha final pode adicionar dificuldades adicionais em várias circunstâncias (concatenar / imprimir vários arquivos de texto, analisar com ferramentas de linha de comando típicas, editores mínimos como busyboxo vietc).
Mtraceur # 8/16

(1) Antes do VMS, o RT-11 RSX-11 TOPS-10 tinha sistemas de arquivos precisos apenas para um bloco e precisava de um caractere EOF. O mesmo aconteceu com o CP / M, que aparentemente o copiou do DEC e, por sua vez, foi copiado no início do MS-DOS e depois passado para o Windows. (2) Em Unix é o driver tty não o shell, conforme descrito com mais detalhes por JohanM, embora as pessoas geralmente executar escudos em dispositivos tty.
Dave_thompson_085

Claro - o DEC estava de volta lá (e observe que eu mencionei versões mais antigas). Se era a origem do recurso CP / M seria um tópico interessante a ser explorado (não aqui); Mencionei esses casos para dar uma base às alternativas.
21416 Thomas Thomas Dickey

7

EOF não é um personagem. É um estado que indica que não há mais caracteres para ler de um fluxo de arquivos. Ao inserir o comando EOF no terminal, você está sinalizando ao sistema operacional para fechar o fluxo de entrada, sem colocar um caractere especial.


11
Sim, mas na tabela ASCII, o EOF é 26, então pensei que o último byte fosse a representação binária de 26. Então, como um programa que lê uma entrada sabe onde termina?
sworwitz

O ASCII foi criado para transmitir informações através de uma rede. Nesse caso, você precisa de um caractere EOF. (O ASCII também possuía muitos códigos de controle. Nem tudo era imprimível.) No caso de fluxos de arquivos, o tamanho do arquivo já é conhecido pelo sistema de arquivos, para que o sistema operacional possa saber quando não há mais dados para ler.
Munir

@sworwitz: No que diz respeito a C, as funções de leitura de entrada que retornam um caractere por chamada retornam um int (geralmente um número de 32 bits, mas deve ter no mínimo 16 bits), não um caractere. A função sinaliza e EOF retornando -1 (0xffffffff), que não é um valor válido de 8 bits, portanto não será confundido por nenhum caractere ASCII, nem mesmo por 0xff. As funções que retornam uma sequência também retornam o comprimento dos dados lidos. Esse comprimento pode ser usado para sinalizar nenhum dado ou final de dados (novamente, o comprimento pode ser -1). Finalmente, há também uma função que você pode chamar que vai dizer se um fluxo chegou ao fim
slebetman

Ok obrigado! Então, quando no bash eu pressiono Ctrl + d eu insiro o caractere ASCII, certo?
21416 Swordwitz

@sworwitz Não exatamente. Antes de bashcolocar as mãos na entrada, ela é massageada pelo driver TTY. Este driver intercepta Ctrl-D e envia um EOF para bash (Onde EOF não é um personagem, mas um estatuto especial de arquivo)
Stig Hemmer
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.