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 Cando pensamos nun arquivo, o que vén á mente é un documento de Microsoft Word, 5 00:00:11,000 --> 00:00:14,000 unha imaxe JPEG ou unha música MP3, 6 00:00:14,000 --> 00:00:17,000 e interactuar con cada un destes tipos de arquivos de diferentes xeitos. 7 00:00:17,000 --> 00:00:20,000 Por exemplo, nun documento de Word, engadir texto 8 00:00:20,000 --> 00:00:24,000 mentres unha imaxe JPEG podemos cortar os bordos ou retocar as cores. 9 00:00:24,000 --> 00:00:28,000 Con todo, baixo a capa de todos os ficheiros no noso ordenador son nada máis 10 00:00:28,000 --> 00:00:31,000 dunha longa secuencia de ceros e uns. 11 00:00:31,000 --> 00:00:33,000 É ata a aplicación específica que interactúa co arquivo 12 00:00:33,000 --> 00:00:38,000 para decidir como procesar esa longa secuencia e presenta-lo para o usuario. 13 00:00:38,000 --> 00:00:41,000 Por unha banda, un documento pode ver só un byte, 14 00:00:41,000 --> 00:00:45,000 ou oito ceros e uns, e amosar un carácter ASCII na pantalla. 15 00:00:45,000 --> 00:00:48,000 Por outra banda, unha imaxe de mapa de bits pode ver 3 bytes, 16 00:00:48,000 --> 00:00:50,000 ou 24 ceros e uns, 17 00:00:50,000 --> 00:00:53,000 e interpretala los como tres números hexadecimais 18 00:00:53,000 --> 00:00:56,000 que representan os valores de vermello, verde e azul 19 00:00:56,000 --> 00:00:58,000 nun pixel dunha imaxe. 20 00:00:58,000 --> 00:01:01,000 O que poden ollar como na pantalla, no seu núcleo, 21 00:01:01,000 --> 00:01:05,000 arquivos non son nada máis que unha secuencia de ceros e uns. 22 00:01:05,000 --> 00:01:08,000 Entón imos mergullar para ver como realmente manipular eses ceros e uns 23 00:01:08,000 --> 00:01:12,000 cando se trata de escribir e ler un arquivo. 24 00:01:12,000 --> 00:01:15,000 >> Vou comezar por división lo en un proceso de 3-parte sinxelo. 25 00:01:15,000 --> 00:01:19,000 A continuación, vou mergullo en dous exemplos de código que demostran estas tres partes. 26 00:01:19,000 --> 00:01:23,000 Finalmente, eu vou revisar o proceso e algúns dos seus detalles máis importantes. 27 00:01:23,000 --> 00:01:25,000 Como ocorre con calquera arquivo que senta no seu escritorio, 28 00:01:25,000 --> 00:01:28,000 A primeira cousa a facer é abri-lo. 29 00:01:28,000 --> 00:01:31,000 C facemos iso declarando un punteiro para unha estrutura predefinida 30 00:01:31,000 --> 00:01:33,000 que representa un ficheiro no disco. 31 00:01:33,000 --> 00:01:38,460 Nesta chamada de función, tamén decidir se quere escribir ou ler a partir do ficheiro. 32 00:01:38,460 --> 00:01:41,660 A continuación, facemos a lectura real e da escritura. 33 00:01:41,660 --> 00:01:44,800 Hai un número de funcións especializadas, podemos utilizar nesta parte, 34 00:01:44,800 --> 00:01:48,790 e case todos eles comezan coa letra F, que está a arquivo. 35 00:01:48,790 --> 00:01:53,560 Pasado, semellante aos X vermellas pequenas na parte superior dos arquivos abrir no seu ordenador, 36 00:01:53,560 --> 00:01:56,680 imos pechar o ficheiro con unha chamada de función final. 37 00:01:56,680 --> 00:01:59,540 Agora que temos unha idea xeral do que imos facer, 38 00:01:59,540 --> 00:02:02,000 imos mergullar no código. 39 00:02:02,000 --> 00:02:06,100 >> Neste directorio, temos dous arquivos C e os seus arquivos executable correspondentes. 40 00:02:06,100 --> 00:02:09,710 O programa da máquina de escribir ten un argumento de liña de comandos, 41 00:02:09,710 --> 00:02:12,060 o nome do documento que desexa crear. 42 00:02:12,060 --> 00:02:16,160 Neste caso, imos chamalo Doc.txt. 43 00:02:16,160 --> 00:02:19,080 Imos executar o programa e introduce un par de liñas. 44 00:02:19,080 --> 00:02:23,660 Oi O meu nome é Jason. 45 00:02:23,660 --> 00:02:26,710 Por fin, imos escribir "Quit". 46 00:02:26,710 --> 00:02:29,720 Agora listar todos os ficheiros no directorio, 47 00:02:29,720 --> 00:02:33,770 vemos que existe un novo documento chamado Doc.txt. 48 00:02:34,190 --> 00:02:36,110 Ese é o arquivo de programa recén criado. 49 00:02:36,110 --> 00:02:40,520 E, por suposto, iso non é nada máis que unha longa secuencia de ceros 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 tres liñas de código que celebramos o noso programa - 52 00:02:46,060 --> 00:02:49,060 Oi Maio é o nome Jason. 53 00:02:49,580 --> 00:02:52,090 Pero o que está realmente a suceder cando typewriter.c funciona? 54 00:02:52,810 --> 00:02:55,520 A primeira liña de interese para nós é a liña 24. 55 00:02:55,560 --> 00:02:58,490 Nesta liña, declaramos a nosa punteiro do ficheiro. 56 00:02:59,080 --> 00:03:03,140 A función que retorna este punteiro, fopen, ten dous argumentos. 57 00:03:03,140 --> 00:03:07,440 O primeiro é o nome do ficheiro, incluíndo a extensión do ficheiro, se fose necesario. 58 00:03:07,440 --> 00:03:10,980 Lembre que unha extensión de arquivo non inflúe o ficheiro no seu nivel máis baixo. 59 00:03:10,980 --> 00:03:14,640 Estamos sempre lidando con unha longa secuencia de ceros e uns. 60 00:03:14,640 --> 00:03:19,630 Pero iso non influencia como os arquivos son interpretados e cales aplicacións son utilizados para abri-los. 61 00:03:19,630 --> 00:03:22,290 O segundo argumento para fopen é unha única letra 62 00:03:22,290 --> 00:03:25,300 que representa o que desexa facer despois de abrir o ficheiro. 63 00:03:25,300 --> 00:03:30,630 Hai tres opcións para ese argumento - W, R e A. 64 00:03:30,630 --> 00:03:34,900 Nós escoller w neste caso, porque queremos escribir para o arquivo. 65 00:03:34,900 --> 00:03:38,820 R, como podes imaxinar, é que a lectura do ficheiro. 66 00:03:38,820 --> 00:03:41,760 E un é para engadir ao ficheiro. 67 00:03:41,760 --> 00:03:44,960 Aínda que ambos W e pode ser usado para a gravación de ficheiros, 68 00:03:44,960 --> 00:03:47,460 w vai comezar a escribir a partir do inicio do ficheiro 69 00:03:47,460 --> 00:03:50,810 e potencialmente substituír todos os datos que foron previamente almacenados. 70 00:03:50,810 --> 00:03:54,070 Por defecto, o ficheiro que abrir, se non hai, 71 00:03:54,070 --> 00:03:57,180 é creado no noso directorio actual de operación. 72 00:03:57,180 --> 00:04:00,540 No entanto, se queremos acceder ou crear un arquivo en un lugar diferente, 73 00:04:00,540 --> 00:04:02,650 no primeiro argumento fopen, 74 00:04:02,650 --> 00:04:05,840 podemos especificar un camiño de ficheiro, ademais do nome do ficheiro. 75 00:04:05,840 --> 00:04:09,490 Aínda que a primeira parte deste proceso é só unha liña de código longo, 76 00:04:09,490 --> 00:04:12,350 é sempre unha boa práctica incluír outro conxunto de liñas 77 00:04:12,350 --> 00:04:15,930 que comprobe que o ficheiro foi aberto ou creado. 78 00:04:15,930 --> 00:04:20,300 Se fopen retorna nulo, que non quere seguir adiante co noso programa, 79 00:04:20,300 --> 00:04:23,270 e isto pode ocorrer se o sistema operativo é falta de memoria 80 00:04:23,270 --> 00:04:27,940 ou tentar abrir un arquivo de un cartafol para o que non tiña os permisos axeitadas. 81 00:04:27,940 --> 00:04:31,780 >> A segunda parte do proceso ocorre en malla máquina de escribir do tempo. 82 00:04:31,780 --> 00:04:35,000 Usamos unha función de biblioteca CS50 para a entrada do usuario, 83 00:04:35,000 --> 00:04:37,190 e asumindo que eles non queren saír do programa, 84 00:04:37,190 --> 00:04:41,940 usan os fputs función para sacar a corda e gravala-lo para o arquivo. 85 00:04:41,940 --> 00:04:46,700 fputs é só unha das moitas funcións que poderiamos usar para gravar o ficheiro. 86 00:04:46,700 --> 00:04:51,920 Outros inclúen fwrite, fputc, e mesmo fprintf. 87 00:04:51,920 --> 00:04:54,840 Independentemente da función particular que acaban empregando, non obstante, 88 00:04:54,840 --> 00:04:57,480 todos eles precisan de saber, por medio dos seus argumentos, 89 00:04:57,480 --> 00:04:59,670 polo menos dúas cousas - 90 00:04:59,670 --> 00:05:03,140 o que ten que ser escrito e onde debe ser escrito. 91 00:05:03,140 --> 00:05:07,240 No noso caso, a entrada é a cadea que debe ser escrito 92 00:05:07,240 --> 00:05:11,290 e FP é o punteiro que orienta-nos cara a onde estamos escribindo. 93 00:05:11,290 --> 00:05:15,330 Neste programa, a segunda parte do proceso é moi sinxelo. 94 00:05:15,330 --> 00:05:17,360 Estamos simplemente tomar unha cadea de usuario 95 00:05:17,360 --> 00:05:22,120 e engadir lo directamente para o noso arquivo con pouco ou ningún validación de entrada ou comprobacións de seguridade. 96 00:05:22,120 --> 00:05:26,160 Moitas veces, porén, a parte dous vai ocupar a maior parte do seu código. 97 00:05:26,160 --> 00:05:30,580 Finalmente, a terceira parte é na liña 58, onde se pecha o arquivo. 98 00:05:30,580 --> 00:05:34,860 Aquí chamamos fclose e pasalo a nosa punteiro do ficheiro orixinal. 99 00:05:34,860 --> 00:05:39,500 Na liña seguinte, volvemos cero, sinalizando o fin do noso programa. 100 00:05:39,500 --> 00:05:42,630 E, si, a terceira parte é tan sinxelo coma iso. 101 00:05:42,630 --> 00:05:45,260 >> Imos pasar á lectura de arquivos. 102 00:05:45,260 --> 00:05:48,220 Volver no noso directorio temos un arquivo chamado printer.c. 103 00:05:48,220 --> 00:05:50,910 Imos executa-lo co ficheiro que acabamos de crear - 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 suxire, vai simplemente imprimir o contido do arquivo pasado para el. 106 00:05:58,150 --> 00:06:00,230 E aí temos iso. 107 00:06:00,230 --> 00:06:03,780 As liñas de código que ingresaran anteriormente e gardados en Doc.txt. 108 00:06:03,780 --> 00:06:06,980 Oi O meu nome é Jason. 109 00:06:06,980 --> 00:06:09,120 Se mergullo printer.c, 110 00:06:09,120 --> 00:06:13,570 vemos que unha gran parte do código é semellante ao que acabamos atravesou en typewriter.c. 111 00:06:13,570 --> 00:06:16,720 En realidade a liña 22, onde abrimos o arquivo, 112 00:06:16,720 --> 00:06:19,220 e liña 39, onde nós pechamos o ficheiro, 113 00:06:19,220 --> 00:06:23,890 son ambos case idéntico ao typewriter.c, para salvar argumento fopen segundo. 114 00:06:23,890 --> 00:06:26,510 Esta vez, estamos lendo un ficheiro, 115 00:06:26,510 --> 00:06:29,040 Entón, temos escollido r en vez de w. 116 00:06:29,040 --> 00:06:31,950 Así, imos nos centrarse na segunda parte do proceso. 117 00:06:31,950 --> 00:06:36,060 Na liña 35, como a segunda condición no noso lazo 4, 118 00:06:36,060 --> 00:06:38,590 facemos unha chamada a fgets, 119 00:06:38,590 --> 00:06:42,190 a función de acompañante para fputs de antes. 120 00:06:42,190 --> 00:06:44,660 Desta vez temos tres argumentos. 121 00:06:44,660 --> 00:06:48,810 O primeiro é o punteiro para a matriz de caracteres en que a cadea será almacenado. 122 00:06:48,810 --> 00:06:52,670 O segundo é o número máximo de caracteres a seren lidos. 123 00:06:52,670 --> 00:06:56,010 E o terceiro é o punteiro para o arquivo co cal estamos a traballar. 124 00:06:56,010 --> 00:07:00,780 Vostede vai entender que o loop remata cando fgets retorna nulo. 125 00:07:00,780 --> 00:07:02,940 Hai dúas razóns que iso pode acontecer. 126 00:07:02,940 --> 00:07:05,380 En primeiro lugar, un erro pode ocorrer. 127 00:07:05,380 --> 00:07:10,740 En segundo lugar, e máis probable, a fin do ficheiro alcanzado e os personaxes non máis foron lidos. 128 00:07:10,740 --> 00:07:14,040 No caso de que estea se pregunta, dúas funcións que non existen nos permiten dicir 129 00:07:14,040 --> 00:07:17,160 que a razón é a causa deste punteiro nulo particular. 130 00:07:17,160 --> 00:07:21,090 E non é de sorprender, xa que teñen que ver coa traballar con arquivos, 131 00:07:21,090 --> 00:07:26,940 tanto a función ferror eo inicio función feof coa letra f. 132 00:07:26,940 --> 00:07:32,130 >> Finalmente, antes de concluír, unha nota rápida sobre o fin da función de arquivo, 133 00:07:32,130 --> 00:07:36,690 que, como xa se mencionou, é escrito como feof. 134 00:07:36,690 --> 00:07:41,550 Moitas veces vai atopar-se con tempo e loops para progresivamente ler o seu camiño a través de arquivos. 135 00:07:41,550 --> 00:07:45,790 Así, vai ter unha forma de acabar con estes lazos despois de chegar ao final destes arquivos. 136 00:07:45,790 --> 00:07:50,510 Chamando feof no seu punteiro do ficheiro e comprobar a ver se é verdade 137 00:07:50,510 --> 00:07:52,310 faría exactamente isto. 138 00:07:52,310 --> 00:07:59,820 Así, un loop while coa condición (! Feof (FP)) pode parecer unha solución perfectamente adecuada. 139 00:07:59,820 --> 00:08:03,770 Con todo, dicir que temos unha liña de esquerda no noso arquivo de texto. 140 00:08:03,770 --> 00:08:07,130 Nós imos entrar no noso loop while e todo vai funcionar como planificado. 141 00:08:07,130 --> 00:08:12,750 Na seguinte rolda través, o noso programa vai comprobar a ver se feof de FP é verdade, 142 00:08:12,750 --> 00:08:15,430 pero - e este é o punto crucial para entender aquí - 143 00:08:15,430 --> 00:08:17,770 non será verdade aínda. 144 00:08:17,770 --> 00:08:21,110 Iso porque o obxectivo de feof non é verificar 145 00:08:21,110 --> 00:08:24,400 a próxima chamada a unha función de lectura vai bater ao final do arquivo, 146 00:08:24,400 --> 00:08:28,190 senón para comprobar se hai ou non a fin do ficheiro xa foi alcanzado. 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 liña do noso arquivo vai perfectamente ben, 149 00:08:32,780 --> 00:08:36,210 pero o programa non sabe que se loita ao final do noso arquivo. 150 00:08:36,210 --> 00:08:40,549 Non é ata que fai unha lectura adicional que contraría o final do arquivo. 151 00:08:40,549 --> 00:08:43,210 Así, unha condición correcta sería o seguinte: 152 00:08:43,210 --> 00:08:49,330 fgets e os seus tres argumentos - de saída, tamaño de produción e FP - 153 00:08:49,330 --> 00:08:52,570 e todo isto non é igual a nulo. 154 00:08:52,570 --> 00:08:55,260 Esta é a visión que adoptamos en printer.c, 155 00:08:55,260 --> 00:08:57,890 e, neste caso, tras a saída do lazo, 156 00:08:57,890 --> 00:09:04,290 podería chamar feof ou ferror para informar ao usuario canto á fundamentación específica para saír deste ciclo. 157 00:09:04,290 --> 00:09:08,100 >> Escribir e ler un arquivo é, na súa forma máis básica, 158 00:09:08,100 --> 00:09:10,150 un proceso de 3-parte sinxelo. 159 00:09:10,150 --> 00:09:12,530 Primeiro, abra o arquivo. 160 00:09:12,530 --> 00:09:16,740 En segundo lugar, poñemos algunhas cousas no noso arquivo ou quitar algunhas cousas fóra. 161 00:09:16,740 --> 00:09:19,200 En terceiro lugar, peche o ficheiro. 162 00:09:19,200 --> 00:09:21,170 A primeira ea última son fáciles. 163 00:09:21,170 --> 00:09:23,920 A parte do medio é onde o material está complicado. 164 00:09:23,920 --> 00:09:27,760 E aínda que debaixo do capó que estamos sempre lidando con unha longa secuencia de ceros e uns, 165 00:09:27,760 --> 00:09:30,710 non axuda cando a codificación para engadir unha capa de abstracción 166 00:09:30,710 --> 00:09:35,350 que transforma a secuencia en algo que se parece máis ao que estamos afeitos a ver. 167 00:09:35,350 --> 00:09:39,570 Por exemplo, se estamos a traballar con un arquivo de bitmap de 24 bits, 168 00:09:39,570 --> 00:09:43,290 imos probablemente estar lendo ou escribindo tres bytes de cada vez. 169 00:09:43,290 --> 00:09:46,450 Neste caso, non tería sentido para definir e nomear correctamente 170 00:09:46,450 --> 00:09:48,980 unha estrutura que é de 3 bytes grande. 171 00:09:48,980 --> 00:09:51,410 >> A pesar de traballar con arquivos pode parecer complicado, 172 00:09:51,410 --> 00:09:54,530 usalos nos permite facer algo verdadeiramente notable. 173 00:09:54,530 --> 00:09:58,880 Podemos cambiar o estado do mundo fóra do noso programa, 174 00:09:58,880 --> 00:10:01,730 podemos crear algo que vive alén da vida do noso programa, 175 00:10:01,730 --> 00:10:07,190 ou podemos ata cambiar algo que foi creado antes do noso programa comezou a funcionar. 176 00:10:07,190 --> 00:10:11,210 Interactuar con arquivos é unha parte verdadeiramente poderosa de programación en C. 177 00:10:11,210 --> 00:10:15,300 e estou animado para ver o que vai crear con el no código de vir. 178 00:10:15,300 --> 00:10:19,770 O 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 >> [Risas] 181 00:10:25,940 --> 00:10:29,330 Okay. Un exame. Aquí imos nós. 182 00:10:49,000 --> 00:10:52,140 Cando pensamos nun arquivo - >> Oh, agarde. Sentímolo. 183 00:10:52,140 --> 00:10:56,800 [Risas] Certo. 184 00:11:06,620 --> 00:11:09,970 Hey there. 185 00:11:13,670 --> 00:11:16,310 Cando pensamos nun arquivo - 186 00:11:17,610 --> 00:11:20,710 Cando vostede pensa nun arquivo - Correcto. Dime cando estea listo. 187 00:11:20,710 --> 00:11:22,520 Ah, xenial. 188 00:11:22,520 --> 00:11:26,180 Aínda que a lectura dun teleprompter poida parecer - non. O meu mal.