1 00:00:00,000 --> 00:00:02,000 [Powered by Google Translate] [File I / O] 2 00:00:02,000 --> 00:00:04,000 [Jason Hirschhorn, Harvard University] 3 00:00:04,000 --> 00:00:07,000 [Esta é CS50, CS50.TV] 4 00:00:07,000 --> 00:00:11,000 Quando pensamos em um arquivo, o que vem à mente é um documento do Microsoft Word, 5 00:00:11,000 --> 00:00:14,000 uma imagem JPEG, ou uma música MP3, 6 00:00:14,000 --> 00:00:17,000 e interagir com cada um desses tipos de arquivos de diferentes maneiras. 7 00:00:17,000 --> 00:00:20,000 Por exemplo, em um documento do Word, adicionar texto 8 00:00:20,000 --> 00:00:24,000 enquanto com uma imagem JPEG podemos cortar as bordas ou retocar as cores. 9 00:00:24,000 --> 00:00:28,000 No entanto, sob a capa de todos os arquivos em nosso computador são nada mais 10 00:00:28,000 --> 00:00:31,000 de uma longa seqüência de zeros e uns. 11 00:00:31,000 --> 00:00:33,000 É até a aplicação específica que interage com o arquivo 12 00:00:33,000 --> 00:00:38,000 para decidir como processar essa longa seqüência e apresentá-lo para o usuário. 13 00:00:38,000 --> 00:00:41,000 Por um lado, um documento pode olhar apenas um byte, 14 00:00:41,000 --> 00:00:45,000 ou oito zeros e uns, e exibir um caractere ASCII na tela. 15 00:00:45,000 --> 00:00:48,000 Por outro lado, uma imagem de mapa de bits pode olhar para 3 bytes, 16 00:00:48,000 --> 00:00:50,000 ou 24 zeros e uns, 17 00:00:50,000 --> 00:00:53,000 e interpretá-los como três números hexadecimais 18 00:00:53,000 --> 00:00:56,000 que representam os valores de vermelho, verde e azul 19 00:00:56,000 --> 00:00:58,000 em um pixel de uma imagem. 20 00:00:58,000 --> 00:01:01,000 O que eles podem olhar como na tela, em seu núcleo, 21 00:01:01,000 --> 00:01:05,000 arquivos não são nada mais do que uma sequência de zeros e uns. 22 00:01:05,000 --> 00:01:08,000 Então vamos mergulhar e ver como nós realmente manipular esses zeros e uns 23 00:01:08,000 --> 00:01:12,000 quando se trata de escrever e ler de um arquivo. 24 00:01:12,000 --> 00:01:15,000 >> Vou começar por dividi-lo em um processo de 3-parte simples. 25 00:01:15,000 --> 00:01:19,000 Em seguida, eu vou mergulhar em dois exemplos de código que demonstram estas três partes. 26 00:01:19,000 --> 00:01:23,000 Finalmente, eu vou rever o processo e alguns de seus detalhes mais importantes. 27 00:01:23,000 --> 00:01:25,000 Como acontece com qualquer arquivo que senta em seu desktop, 28 00:01:25,000 --> 00:01:28,000 a primeira coisa a fazer é abri-lo. 29 00:01:28,000 --> 00:01:31,000 Em C fazemos isso declarando um ponteiro para uma estrutura pré-definida 30 00:01:31,000 --> 00:01:33,000 que representa um arquivo no disco. 31 00:01:33,000 --> 00:01:38,460 Nesta chamada de função, também decidir se quer escrever ou ler a partir do arquivo. 32 00:01:38,460 --> 00:01:41,660 Em seguida, fazemos a leitura real e da escrita. 33 00:01:41,660 --> 00:01:44,800 Há um número de funções especializadas, podemos usar nesta parte, 34 00:01:44,800 --> 00:01:48,790 e quase todos eles começam com a letra F, que está para arquivo. 35 00:01:48,790 --> 00:01:53,560 Passado, semelhante aos X vermelhas pequenas no canto superior dos arquivos abrir em seu computador, 36 00:01:53,560 --> 00:01:56,680 vamos fechar o arquivo com uma chamada de função final. 37 00:01:56,680 --> 00:01:59,540 Agora que temos uma idéia geral do que vamos fazer, 38 00:01:59,540 --> 00:02:02,000 vamos mergulhar no código. 39 00:02:02,000 --> 00:02:06,100 >> Neste diretório, temos dois arquivos C e seus arquivos executáveis ​​correspondentes. 40 00:02:06,100 --> 00:02:09,710 O programa da máquina de escrever tem um argumento de linha de comando, 41 00:02:09,710 --> 00:02:12,060 o nome do documento que deseja criar. 42 00:02:12,060 --> 00:02:16,160 Neste caso, vamos chamá-lo Doc.txt. 43 00:02:16,160 --> 00:02:19,080 Vamos executar o programa e insira um par de linhas. 44 00:02:19,080 --> 00:02:23,660 Oi. Meu nome é Jason. 45 00:02:23,660 --> 00:02:26,710 Por fim, vamos digitar "quit". 46 00:02:26,710 --> 00:02:29,720 Se agora listar todos os arquivos no diretório, 47 00:02:29,720 --> 00:02:33,770 vemos que existe um novo documento chamado Doc.txt. 48 00:02:34,190 --> 00:02:36,110 Esse é o arquivo de programa recém-criado. 49 00:02:36,110 --> 00:02:40,520 E, claro, isso também não é nada mais do que uma longa seqüência de zeros e uns. 50 00:02:41,100 --> 00:02:43,260 Se abrirmos este novo arquivo, 51 00:02:43,260 --> 00:02:45,870 vemos as três linhas de código que celebramos nosso programa - 52 00:02:46,060 --> 00:02:49,060 Oi. Maio é o nome Jason. 53 00:02:49,580 --> 00:02:52,090 Mas o que está realmente acontecendo quando typewriter.c funciona? 54 00:02:52,810 --> 00:02:55,520 A primeira linha de interesse para nós é a linha 24. 55 00:02:55,560 --> 00:02:58,490 Nesta linha, declaramos nossa ponteiro de arquivo. 56 00:02:59,080 --> 00:03:03,140 A função que retorna este ponteiro, fopen, tem dois argumentos. 57 00:03:03,140 --> 00:03:07,440 O primeiro é o nome do arquivo, incluindo a extensão do arquivo, se necessário. 58 00:03:07,440 --> 00:03:10,980 Lembre-se que uma extensão de arquivo não influencia o arquivo em seu nível mais baixo. 59 00:03:10,980 --> 00:03:14,640 Estamos sempre lidando com uma longa seqüência de zeros e uns. 60 00:03:14,640 --> 00:03:19,630 Mas isso não influência como os arquivos são interpretados e quais aplicativos são utilizados para abri-los. 61 00:03:19,630 --> 00:03:22,290 O segundo argumento para fopen é uma única letra 62 00:03:22,290 --> 00:03:25,300 que representa o que pretende fazer depois de abrir o arquivo. 63 00:03:25,300 --> 00:03:30,630 Há três opções para esse argumento - W, R e A. 64 00:03:30,630 --> 00:03:34,900 Nós escolhemos w neste caso, porque queremos escrever para o arquivo. 65 00:03:34,900 --> 00:03:38,820 R, como você pode imaginar, é que a leitura do arquivo. 66 00:03:38,820 --> 00:03:41,760 E um é para acrescentar ao arquivo. 67 00:03:41,760 --> 00:03:44,960 Embora ambos w e um pode ser utilizado para a gravação de arquivos, 68 00:03:44,960 --> 00:03:47,460 w vai começar a escrever a partir do início do arquivo 69 00:03:47,460 --> 00:03:50,810 e potencialmente substituir todos os dados que tenham sido previamente armazenados. 70 00:03:50,810 --> 00:03:54,070 Por padrão, o arquivo que abrir, se não existir, 71 00:03:54,070 --> 00:03:57,180 é criado em nosso diretório atual de operação. 72 00:03:57,180 --> 00:04:00,540 No entanto, se queremos acessar ou criar um arquivo em um local diferente, 73 00:04:00,540 --> 00:04:02,650 no primeiro argumento de fopen, 74 00:04:02,650 --> 00:04:05,840 podemos especificar um caminho de arquivo, além do nome do arquivo. 75 00:04:05,840 --> 00:04:09,490 Embora a primeira parte deste processo é apenas uma linha de código longo, 76 00:04:09,490 --> 00:04:12,350 é sempre uma boa prática incluir um outro conjunto de linhas 77 00:04:12,350 --> 00:04:15,930 que verifique se o arquivo foi aberto ou criado. 78 00:04:15,930 --> 00:04:20,300 Se fopen retorna nulo, que não gostaria de seguir em frente com o nosso programa, 79 00:04:20,300 --> 00:04:23,270 e isso pode acontecer se o sistema operacional é falta de memória 80 00:04:23,270 --> 00:04:27,940 ou se tentar abrir um arquivo de um diretório para o qual não tinha as permissões adequadas. 81 00:04:27,940 --> 00:04:31,780 >> A segunda parte do processo ocorre em malha máquina de escrever do tempo. 82 00:04:31,780 --> 00:04:35,000 Nós usamos uma função de biblioteca CS50 para obter a entrada do usuário, 83 00:04:35,000 --> 00:04:37,190 e assumindo que eles não querem sair do programa, 84 00:04:37,190 --> 00:04:41,940 usamos os fputs função para tirar a corda e escrevê-lo para o arquivo. 85 00:04:41,940 --> 00:04:46,700 fputs é apenas uma das muitas funções que poderíamos usar para gravar o arquivo. 86 00:04:46,700 --> 00:04:51,920 Outros incluem fwrite, fputc, e mesmo fprintf. 87 00:04:51,920 --> 00:04:54,840 Independentemente da função particular que acabam utilizando, no entanto, 88 00:04:54,840 --> 00:04:57,480 todos eles precisam de saber, por meio de seus argumentos, 89 00:04:57,480 --> 00:04:59,670 pelo menos duas coisas - 90 00:04:59,670 --> 00:05:03,140 o que precisa ser escrito e onde ele precisa ser escrito. 91 00:05:03,140 --> 00:05:07,240 No nosso caso, a entrada é a cadeia que precisa ser escrito 92 00:05:07,240 --> 00:05:11,290 e fp é o ponteiro que orienta-nos para onde estamos escrevendo. 93 00:05:11,290 --> 00:05:15,330 Neste programa, a segunda parte do processo é bastante simples. 94 00:05:15,330 --> 00:05:17,360 Estamos simplesmente tomar uma string do usuário 95 00:05:17,360 --> 00:05:22,120 e adicioná-lo diretamente para o nosso arquivo com pouco ou nenhuma validação de entrada ou verificações de segurança. 96 00:05:22,120 --> 00:05:26,160 Muitas vezes, porém, a parte dois vai ocupar a maior parte do seu código. 97 00:05:26,160 --> 00:05:30,580 Finalmente, a terceira parte é na linha 58, onde se feche o arquivo. 98 00:05:30,580 --> 00:05:34,860 Aqui chamamos fclose e passá-lo a nossa ponteiro do arquivo original. 99 00:05:34,860 --> 00:05:39,500 Na linha seguinte, voltamos zero, sinalizando o fim de nosso programa. 100 00:05:39,500 --> 00:05:42,630 E, sim, a terceira parte é tão simples como isso. 101 00:05:42,630 --> 00:05:45,260 >> Vamos passar para a leitura de arquivos. 102 00:05:45,260 --> 00:05:48,220 Voltar em nosso diretório temos um arquivo chamado printer.c. 103 00:05:48,220 --> 00:05:50,910 Vamos executá-lo com o arquivo que acabamos de criar - 104 00:05:50,910 --> 00:05:53,350 Doc.txt. 105 00:05:53,350 --> 00:05:58,150 Este programa, como o nome sugere, vai simplesmente imprimir o conteúdo do arquivo passado para ele. 106 00:05:58,150 --> 00:06:00,230 E aí temos isso. 107 00:06:00,230 --> 00:06:03,780 As linhas de código que tinha digitado anteriormente e salvas em Doc.txt. 108 00:06:03,780 --> 00:06:06,980 Oi. Meu nome é Jason. 109 00:06:06,980 --> 00:06:09,120 Se mergulhar printer.c, 110 00:06:09,120 --> 00:06:13,570 vemos que uma grande parte do código é semelhante ao que acabamos atravessou em typewriter.c. 111 00:06:13,570 --> 00:06:16,720 Na verdade a linha 22, onde abrimos o arquivo, 112 00:06:16,720 --> 00:06:19,220 e linha 39, onde nós fechamos o arquivo, 113 00:06:19,220 --> 00:06:23,890 são ambos quase idêntico ao typewriter.c, para salvar argumento fopen segundo. 114 00:06:23,890 --> 00:06:26,510 Desta vez, estamos lendo de um arquivo, 115 00:06:26,510 --> 00:06:29,040 Então, temos escolhido r em vez de w. 116 00:06:29,040 --> 00:06:31,950 Assim, vamos nos concentrar na segunda parte do processo. 117 00:06:31,950 --> 00:06:36,060 Na linha 35, como a segunda condição em nosso laço 4, 118 00:06:36,060 --> 00:06:38,590 fazemos uma chamada para fgets, 119 00:06:38,590 --> 00:06:42,190 a função de companheiro para fputs de antes. 120 00:06:42,190 --> 00:06:44,660 Desta vez temos três argumentos. 121 00:06:44,660 --> 00:06:48,810 O primeiro é o ponteiro para a matriz de caracteres em que a cadeia será armazenado. 122 00:06:48,810 --> 00:06:52,670 O segundo é o número máximo de caracteres a serem lidos. 123 00:06:52,670 --> 00:06:56,010 E o terceiro é o ponteiro para o arquivo com o qual estamos trabalhando. 124 00:06:56,010 --> 00:07:00,780 Você vai perceber que o loop termina quando fgets retorna nulo. 125 00:07:00,780 --> 00:07:02,940 Há duas razões que isso pode ter acontecido. 126 00:07:02,940 --> 00:07:05,380 Primeiro, um erro pode ter ocorrido. 127 00:07:05,380 --> 00:07:10,740 Segundo, e mais provável, o fim do arquivo foi alcançado e os personagens não mais foram lidos. 128 00:07:10,740 --> 00:07:14,040 No caso você esteja se perguntando, duas funções que não existem nos permitem dizer 129 00:07:14,040 --> 00:07:17,160 que a razão é a causa para este ponteiro nulo particular. 130 00:07:17,160 --> 00:07:21,090 E, não é de surpreender, já que eles têm a ver com trabalhar com arquivos, 131 00:07:21,090 --> 00:07:26,940 tanto a função ferror eo início função feof com a letra f. 132 00:07:26,940 --> 00:07:32,130 >> Finalmente, antes de concluir, uma nota rápida sobre o fim da função de arquivo, 133 00:07:32,130 --> 00:07:36,690 que, como já mencionado, é escrito como feof. 134 00:07:36,690 --> 00:07:41,550 Muitas vezes você vai encontrar-se com tempo e loops para progressivamente ler o seu caminho através de arquivos. 135 00:07:41,550 --> 00:07:45,790 Assim, você vai precisar de uma forma de acabar com estes laços depois de chegar ao final desses arquivos. 136 00:07:45,790 --> 00:07:50,510 Chamando feof em seu ponteiro de arquivo e verificar para ver se é verdade 137 00:07:50,510 --> 00:07:52,310 faria exatamente isso. 138 00:07:52,310 --> 00:07:59,820 Assim, um loop while com a condição (! Feof (fp)) pode parecer uma solução perfeitamente adequada. 139 00:07:59,820 --> 00:08:03,770 No entanto, dizer que temos uma linha de esquerda em nosso arquivo de texto. 140 00:08:03,770 --> 00:08:07,130 Nós vamos entrar no nosso loop while e tudo vai funcionar como planejado. 141 00:08:07,130 --> 00:08:12,750 Na próxima rodada através, nosso programa vai verificar para ver se feof de fp é verdade, 142 00:08:12,750 --> 00:08:15,430 mas - e este é o ponto crucial para entender aqui - 143 00:08:15,430 --> 00:08:17,770 não será verdade ainda. 144 00:08:17,770 --> 00:08:21,110 Isso porque o objetivo de feof não é verificar 145 00:08:21,110 --> 00:08:24,400 se a próxima chamada para uma função de leitura vai bater no final do arquivo, 146 00:08:24,400 --> 00:08:28,190 mas sim para verificar se há ou não o fim do arquivo já foi alcançado. 147 00:08:28,190 --> 00:08:30,140 No caso deste exemplo, 148 00:08:30,140 --> 00:08:32,780 ler a última linha do nosso arquivo vai perfeitamente bem, 149 00:08:32,780 --> 00:08:36,210 mas o programa ainda não sabe que nós batemos o final do nosso arquivo. 150 00:08:36,210 --> 00:08:40,549 Não é até que ele faz uma leitura adicional que contraria o final do arquivo. 151 00:08:40,549 --> 00:08:43,210 Assim, uma condição correcta seria o seguinte: 152 00:08:43,210 --> 00:08:49,330 fgets e seus três argumentos - de saída, tamanho da produção e FP - 153 00:08:49,330 --> 00:08:52,570 e tudo isso não é igual a nulo. 154 00:08:52,570 --> 00:08:55,260 Esta é a abordagem que adotamos em printer.c, 155 00:08:55,260 --> 00:08:57,890 e, neste caso, após a saída do laço, 156 00:08:57,890 --> 00:09:04,290 você poderia chamar feof ou ferror para informar ao usuário quanto à fundamentação específica para sair deste ciclo. 157 00:09:04,290 --> 00:09:08,100 >> Escrever e ler de um arquivo é, em sua forma mais básica, 158 00:09:08,100 --> 00:09:10,150 um processo de 3-parte simples. 159 00:09:10,150 --> 00:09:12,530 Primeiro, abra o arquivo. 160 00:09:12,530 --> 00:09:16,740 Segundo, nós colocamos algumas coisas em nosso arquivo ou tirar algumas coisas de fora. 161 00:09:16,740 --> 00:09:19,200 Em terceiro lugar, feche o arquivo. 162 00:09:19,200 --> 00:09:21,170 A primeira ea última são fáceis. 163 00:09:21,170 --> 00:09:23,920 A parte do meio é onde o material está complicado. 164 00:09:23,920 --> 00:09:27,760 E embora debaixo do capô que estamos sempre lidando com uma longa seqüência de zeros e uns, 165 00:09:27,760 --> 00:09:30,710 ele não ajuda quando a codificação para adicionar uma camada de abstração 166 00:09:30,710 --> 00:09:35,350 que transforma a seqüência em algo que se parece mais com o que estamos acostumados a ver. 167 00:09:35,350 --> 00:09:39,570 Por exemplo, se estamos trabalhando com um arquivo de bitmap de 24 bits, 168 00:09:39,570 --> 00:09:43,290 vamos provavelmente estar lendo ou escrevendo três bytes de cada vez. 169 00:09:43,290 --> 00:09:46,450 Nesse caso, não faria sentido para definir e nomear adequadamente 170 00:09:46,450 --> 00:09:48,980 uma estrutura que é de 3 bytes grande. 171 00:09:48,980 --> 00:09:51,410 >> Apesar de trabalhar com arquivos pode parecer complicado, 172 00:09:51,410 --> 00:09:54,530 utilizá-los nos permite fazer algo verdadeiramente notável. 173 00:09:54,530 --> 00:09:58,880 Nós podemos mudar o estado do mundo fora do nosso programa, 174 00:09:58,880 --> 00:10:01,730 podemos criar algo que vive além da vida do nosso programa, 175 00:10:01,730 --> 00:10:07,190 ou podemos até mudar algo que foi criado antes do nosso programa começou a correr. 176 00:10:07,190 --> 00:10:11,210 Interagindo com arquivos é uma parte verdadeiramente poderosa de programação em C. 177 00:10:11,210 --> 00:10:15,300 e estou animado para ver o que você vai criar com ele no código de vir. 178 00:10:15,300 --> 00:10:19,770 Meu nome é Jason Hirschhorn. Este é CS50. 179 00:10:19,770 --> 00:10:21,770 [CS50.TV] 180 00:10:21,770 --> 00:10:25,940 >> [Risos] 181 00:10:25,940 --> 00:10:29,330 Okay. Um exame. Aqui vamos nós. 182 00:10:49,000 --> 00:10:52,140 Quando pensamos em um arquivo - >> Oh, espere. Desculpe. 183 00:10:52,140 --> 00:10:56,800 [Risos] Certo. 184 00:11:06,620 --> 00:11:09,970 Hey there. 185 00:11:13,670 --> 00:11:16,310 Quando pensamos em um arquivo - 186 00:11:17,610 --> 00:11:20,710 Quando você pensa em um arquivo - Certo. Diga-me quando estiver pronto. 187 00:11:20,710 --> 00:11:22,520 Ah, ótimo. 188 00:11:22,520 --> 00:11:26,180 Embora a leitura de um teleprompter possa parecer - não. Meu ruim.