[Powered by Google Translate] [File I / O] [Jason Hirschhorn, Harvard University] [Esta é CS50, CS50.TV] Quando pensamos em um arquivo, o que vem à mente é um documento do Microsoft Word, uma imagem JPEG, ou uma música MP3, e interagir com cada um desses tipos de arquivos de diferentes maneiras. Por exemplo, em um documento do Word, adicionar texto enquanto com uma imagem JPEG podemos cortar as bordas ou retocar as cores. No entanto, sob a capa de todos os arquivos em nosso computador são nada mais de uma longa seqüência de zeros e uns. É até a aplicação específica que interage com o arquivo para decidir como processar essa longa seqüência e apresentá-lo para o usuário. Por um lado, um documento pode olhar apenas um byte, ou oito zeros e uns, e exibir um caractere ASCII na tela. Por outro lado, uma imagem de mapa de bits pode olhar para 3 bytes, ou 24 zeros e uns, e interpretá-los como três números hexadecimais que representam os valores de vermelho, verde e azul em um pixel de uma imagem. O que eles podem olhar como na tela, em seu núcleo, arquivos não são nada mais do que uma sequência de zeros e uns. Então vamos mergulhar e ver como nós realmente manipular esses zeros e uns quando se trata de escrever e ler de um arquivo. Vou começar por dividi-lo em um processo de 3-parte simples. Em seguida, eu vou mergulhar em dois exemplos de código que demonstram estas três partes. Finalmente, eu vou rever o processo e alguns de seus detalhes mais importantes. Como acontece com qualquer arquivo que senta em seu desktop, a primeira coisa a fazer é abri-lo. Em C fazemos isso declarando um ponteiro para uma estrutura pré-definida que representa um arquivo no disco. Nesta chamada de função, também decidir se quer escrever ou ler a partir do arquivo. Em seguida, fazemos a leitura real e da escrita. Há um número de funções especializadas, podemos usar nesta parte, e quase todos eles começam com a letra F, que está para arquivo. Passado, semelhante aos X vermelhas pequenas no canto superior dos arquivos abrir em seu computador, vamos fechar o arquivo com uma chamada de função final. Agora que temos uma idéia geral do que vamos fazer, vamos mergulhar no código. Neste diretório, temos dois arquivos C e seus arquivos executáveis ​​correspondentes. O programa da máquina de escrever tem um argumento de linha de comando, o nome do documento que deseja criar. Neste caso, vamos chamá-lo Doc.txt. Vamos executar o programa e insira um par de linhas. Oi. Meu nome é Jason. Por fim, vamos digitar "quit". Se agora listar todos os arquivos no diretório, vemos que existe um novo documento chamado Doc.txt. Esse é o arquivo de programa recém-criado. E, claro, isso também não é nada mais do que uma longa seqüência de zeros e uns. Se abrirmos este novo arquivo, vemos as três linhas de código que celebramos nosso programa - Oi. Maio é o nome Jason. Mas o que está realmente acontecendo quando typewriter.c funciona? A primeira linha de interesse para nós é a linha 24. Nesta linha, declaramos nossa ponteiro de arquivo. A função que retorna este ponteiro, fopen, tem dois argumentos. O primeiro é o nome do arquivo, incluindo a extensão do arquivo, se necessário. Lembre-se que uma extensão de arquivo não influencia o arquivo em seu nível mais baixo. Estamos sempre lidando com uma longa seqüência de zeros e uns. Mas isso não influência como os arquivos são interpretados e quais aplicativos são utilizados para abri-los. O segundo argumento para fopen é uma única letra que representa o que pretende fazer depois de abrir o arquivo. Há três opções para esse argumento - W, R e A. Nós escolhemos w neste caso, porque queremos escrever para o arquivo. R, como você pode imaginar, é que a leitura do arquivo. E um é para acrescentar ao arquivo. Embora ambos w e um pode ser utilizado para a gravação de arquivos, w vai começar a escrever a partir do início do arquivo e potencialmente substituir todos os dados que tenham sido previamente armazenados. Por padrão, o arquivo que abrir, se não existir, é criado em nosso diretório atual de operação. No entanto, se queremos acessar ou criar um arquivo em um local diferente, no primeiro argumento de fopen, podemos especificar um caminho de arquivo, além do nome do arquivo. Embora a primeira parte deste processo é apenas uma linha de código longo, é sempre uma boa prática incluir um outro conjunto de linhas que verifique se o arquivo foi aberto ou criado. Se fopen retorna nulo, que não gostaria de seguir em frente com o nosso programa, e isso pode acontecer se o sistema operacional é falta de memória ou se tentar abrir um arquivo de um diretório para o qual não tinha as permissões adequadas. A segunda parte do processo ocorre em malha máquina de escrever do tempo. Nós usamos uma função de biblioteca CS50 para obter a entrada do usuário, e assumindo que eles não querem sair do programa, usamos os fputs função para tirar a corda e escrevê-lo para o arquivo. fputs é apenas uma das muitas funções que poderíamos usar para gravar o arquivo. Outros incluem fwrite, fputc, e mesmo fprintf. Independentemente da função particular que acabam utilizando, no entanto, todos eles precisam de saber, por meio de seus argumentos, pelo menos duas coisas - o que precisa ser escrito e onde ele precisa ser escrito. No nosso caso, a entrada é a cadeia que precisa ser escrito e fp é o ponteiro que orienta-nos para onde estamos escrevendo. Neste programa, a segunda parte do processo é bastante simples. Estamos simplesmente tomar uma string do usuário e adicioná-lo diretamente para o nosso arquivo com pouco ou nenhuma validação de entrada ou verificações de segurança. Muitas vezes, porém, a parte dois vai ocupar a maior parte do seu código. Finalmente, a terceira parte é na linha 58, onde se feche o arquivo. Aqui chamamos fclose e passá-lo a nossa ponteiro do arquivo original. Na linha seguinte, voltamos zero, sinalizando o fim de nosso programa. E, sim, a terceira parte é tão simples como isso. Vamos passar para a leitura de arquivos. Voltar em nosso diretório temos um arquivo chamado printer.c. Vamos executá-lo com o arquivo que acabamos de criar - Doc.txt. Este programa, como o nome sugere, vai simplesmente imprimir o conteúdo do arquivo passado para ele. E aí temos isso. As linhas de código que tinha digitado anteriormente e salvas em Doc.txt. Oi. Meu nome é Jason. Se mergulhar printer.c, vemos que uma grande parte do código é semelhante ao que acabamos atravessou em typewriter.c. Na verdade a linha 22, onde abrimos o arquivo, e linha 39, onde nós fechamos o arquivo, são ambos quase idêntico ao typewriter.c, para salvar argumento fopen segundo. Desta vez, estamos lendo de um arquivo, Então, temos escolhido r em vez de w. Assim, vamos nos concentrar na segunda parte do processo. Na linha 35, como a segunda condição em nosso laço 4, fazemos uma chamada para fgets, a função de companheiro para fputs de antes. Desta vez temos três argumentos. O primeiro é o ponteiro para a matriz de caracteres em que a cadeia será armazenado. O segundo é o número máximo de caracteres a serem lidos. E o terceiro é o ponteiro para o arquivo com o qual estamos trabalhando. Você vai perceber que o loop termina quando fgets retorna nulo. Há duas razões que isso pode ter acontecido. Primeiro, um erro pode ter ocorrido. Segundo, e mais provável, o fim do arquivo foi alcançado e os personagens não mais foram lidos. No caso você esteja se perguntando, duas funções que não existem nos permitem dizer que a razão é a causa para este ponteiro nulo particular. E, não é de surpreender, já que eles têm a ver com trabalhar com arquivos, tanto a função ferror eo início função feof com a letra f. Finalmente, antes de concluir, uma nota rápida sobre o fim da função de arquivo, que, como já mencionado, é escrito como feof. Muitas vezes você vai encontrar-se com tempo e loops para progressivamente ler o seu caminho através de arquivos. Assim, você vai precisar de uma forma de acabar com estes laços depois de chegar ao final desses arquivos. Chamando feof em seu ponteiro de arquivo e verificar para ver se é verdade faria exatamente isso. Assim, um loop while com a condição (! Feof (fp)) pode parecer uma solução perfeitamente adequada. No entanto, dizer que temos uma linha de esquerda em nosso arquivo de texto. Nós vamos entrar no nosso loop while e tudo vai funcionar como planejado. Na próxima rodada através, nosso programa vai verificar para ver se feof de fp é verdade, mas - e este é o ponto crucial para entender aqui - não será verdade ainda. Isso porque o objetivo de feof não é verificar se a próxima chamada para uma função de leitura vai bater no final do arquivo, mas sim para verificar se há ou não o fim do arquivo já foi alcançado. No caso deste exemplo, ler a última linha do nosso arquivo vai perfeitamente bem, mas o programa ainda não sabe que nós batemos o final do nosso arquivo. Não é até que ele faz uma leitura adicional que contraria o final do arquivo. Assim, uma condição correcta seria o seguinte: fgets e seus três argumentos - de saída, tamanho da produção e FP - e tudo isso não é igual a nulo. Esta é a abordagem que adotamos em printer.c, e, neste caso, após a saída do laço, você poderia chamar feof ou ferror para informar ao usuário quanto à fundamentação específica para sair deste ciclo. Escrever e ler de um arquivo é, em sua forma mais básica, um processo de 3-parte simples. Primeiro, abra o arquivo. Segundo, nós colocamos algumas coisas em nosso arquivo ou tirar algumas coisas de fora. Em terceiro lugar, feche o arquivo. A primeira ea última são fáceis. A parte do meio é onde o material está complicado. E embora debaixo do capô que estamos sempre lidando com uma longa seqüência de zeros e uns, ele não ajuda quando a codificação para adicionar uma camada de abstração que transforma a seqüência em algo que se parece mais com o que estamos acostumados a ver. Por exemplo, se estamos trabalhando com um arquivo de bitmap de 24 bits, vamos provavelmente estar lendo ou escrevendo três bytes de cada vez. Nesse caso, não faria sentido para definir e nomear adequadamente uma estrutura que é de 3 bytes grande. Apesar de trabalhar com arquivos pode parecer complicado, utilizá-los nos permite fazer algo verdadeiramente notável. Nós podemos mudar o estado do mundo fora do nosso programa, podemos criar algo que vive além da vida do nosso programa, ou podemos até mudar algo que foi criado antes do nosso programa começou a correr. Interagindo com arquivos é uma parte verdadeiramente poderosa de programação em C. e estou animado para ver o que você vai criar com ele no código de vir. Meu nome é Jason Hirschhorn. Este é CS50. [CS50.TV] [Risos] Okay. Um exame. Aqui vamos nós. Quando pensamos em um arquivo - >> Oh, espere. Desculpe. [Risos] Certo. Hey there. Quando pensamos em um arquivo - Quando você pensa em um arquivo - Certo. Diga-me quando estiver pronto. Ah, ótimo. Embora a leitura de um teleprompter possa parecer - não. Meu ruim.