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 es CS50, CS50.TV] 4 00:00:07,000 --> 00:00:11,000 Cuando pensamos en un archivo, lo que viene a la mente es un documento de Microsoft Word, 5 00:00:11,000 --> 00:00:14,000 una imagen JPEG, o una canción MP3, 6 00:00:14,000 --> 00:00:17,000 y nos relacionamos con cada uno de estos tipos de archivos de diferentes maneras. 7 00:00:17,000 --> 00:00:20,000 Por ejemplo, en un documento de Word que añadir el texto 8 00:00:20,000 --> 00:00:24,000 mientras que con una imagen JPEG que podríamos recortar los bordes o retocar los colores. 9 00:00:24,000 --> 00:00:28,000 Sin embargo, bajo el capó de todos los archivos en nuestro ordenador no son más 10 00:00:28,000 --> 00:00:31,000 de una larga secuencia de ceros y unos. 11 00:00:31,000 --> 00:00:33,000 Todo depende de la aplicación específica que interactúa con el archivo 12 00:00:33,000 --> 00:00:38,000 para decidir cómo procesar esta secuencia larga y presentarla al usuario. 13 00:00:38,000 --> 00:00:41,000 Por un lado, un documento puede parecer en un solo byte, 14 00:00:41,000 --> 00:00:45,000 o 8 ceros y unos, y mostrar un carácter ASCII en la pantalla. 15 00:00:45,000 --> 00:00:48,000 Por otra parte, una imagen de mapa de bits puede mirar a 3 bytes, 16 00:00:48,000 --> 00:00:50,000 o 24 ceros y unos, 17 00:00:50,000 --> 00:00:53,000 y las interpretan como tres números hexadecimales 18 00:00:53,000 --> 00:00:56,000 que representan los valores de rojo, verde y azul 19 00:00:56,000 --> 00:00:58,000 en un píxel de una imagen. 20 00:00:58,000 --> 00:01:01,000 Digan lo que puede parecer en la pantalla, en el fondo, 21 00:01:01,000 --> 00:01:05,000 archivos no son nada más que una secuencia de ceros y unos. 22 00:01:05,000 --> 00:01:08,000 Así que vamos a bucear y ver cómo realmente manipular estos ceros y unos 23 00:01:08,000 --> 00:01:12,000 cuando se trata de la escritura y lectura de un archivo. 24 00:01:12,000 --> 00:01:15,000 >> Voy a empezar por lo descomponen en un simple proceso de 3 partes. 25 00:01:15,000 --> 00:01:19,000 A continuación, voy a bucear en dos ejemplos de código que muestran estas tres partes. 26 00:01:19,000 --> 00:01:23,000 Por último, voy a revisar el proceso y algunos de sus detalles más importantes. 27 00:01:23,000 --> 00:01:25,000 Al igual que con cualquier archivo que se sienta en su escritorio, 28 00:01:25,000 --> 00:01:28,000 lo primero que debe hacer es abrirlo. 29 00:01:28,000 --> 00:01:31,000 En C hacemos esto al declarar un puntero a una estructura predefinida 30 00:01:31,000 --> 00:01:33,000 que representa un archivo en el disco. 31 00:01:33,000 --> 00:01:38,460 En esta llamada de función, también decidimos si queremos escribir o leer desde el archivo. 32 00:01:38,460 --> 00:01:41,660 A continuación, hacemos la lectura real y la escritura. 33 00:01:41,660 --> 00:01:44,800 Hay una serie de funciones especializadas que podemos utilizar en esta parte, 34 00:01:44,800 --> 00:01:48,790 y casi todos ellos comienzan con la letra F, que corresponde a archivo. 35 00:01:48,790 --> 00:01:53,560 Por último, semejante a la pequeña X roja en la esquina superior de los archivos abiertos en el equipo, 36 00:01:53,560 --> 00:01:56,680 cerramos el archivo con una llamada a la función final. 37 00:01:56,680 --> 00:01:59,540 Ahora que tenemos una idea general de lo que vamos a hacer, 38 00:01:59,540 --> 00:02:02,000 vamos a bucear en el código. 39 00:02:02,000 --> 00:02:06,100 >> En este directorio, tenemos dos archivos de C y sus archivos ejecutables correspondientes. 40 00:02:06,100 --> 00:02:09,710 El programa de máquina de escribir tiene un argumento de línea de comandos, 41 00:02:09,710 --> 00:02:12,060 el nombre del documento que desea crear. 42 00:02:12,060 --> 00:02:16,160 En este caso, vamos a llamarlo doc.txt. 43 00:02:16,160 --> 00:02:19,080 Vamos a ejecutar el programa y entrar en un par de líneas. 44 00:02:19,080 --> 00:02:23,660 Hi. Mi nombre es Jason. 45 00:02:23,660 --> 00:02:26,710 Por último, vamos a escribir "quit". 46 00:02:26,710 --> 00:02:29,720 Si ahora una lista de todos los archivos en este directorio, 47 00:02:29,720 --> 00:02:33,770 vemos que existe un nuevo documento llamado doc.txt. 48 00:02:34,190 --> 00:02:36,110 Ese es el archivo de este programa acaba de crear. 49 00:02:36,110 --> 00:02:40,520 Y, por supuesto, también no es más que una larga secuencia de ceros y unos. 50 00:02:41,100 --> 00:02:43,260 Si abrimos este nuevo archivo, 51 00:02:43,260 --> 00:02:45,870 vemos las 3 líneas de código que entró en nuestro programa - 52 00:02:46,060 --> 00:02:49,060 Hi. Mayo es el nombre de Jason. 53 00:02:49,580 --> 00:02:52,090 Pero lo que realmente sucede cuando se ejecuta typewriter.c? 54 00:02:52,810 --> 00:02:55,520 La primera línea de interés para nosotros es la línea 24. 55 00:02:55,560 --> 00:02:58,490 En esta línea, declaramos nuestro puntero de archivo. 56 00:02:59,080 --> 00:03:03,140 La función que devuelve este indicador, fopen, toma dos argumentos. 57 00:03:03,140 --> 00:03:07,440 El primero es el nombre del archivo incluyendo la extensión de archivo si es apropiado. 58 00:03:07,440 --> 00:03:10,980 Recordemos que una extensión de archivo no influye en el archivo en su nivel más bajo. 59 00:03:10,980 --> 00:03:14,640 Siempre estamos tratando con una larga secuencia de ceros y unos. 60 00:03:14,640 --> 00:03:19,630 Pero sí influye la cantidad de archivos se interpretan y qué aplicaciones se utilizan para abrirlos. 61 00:03:19,630 --> 00:03:22,290 El segundo argumento de fopen es una sola letra 62 00:03:22,290 --> 00:03:25,300 que representa lo que piensa hacer después de abrir el archivo. 63 00:03:25,300 --> 00:03:30,630 Hay tres opciones para este argumento - W, R y A. 64 00:03:30,630 --> 00:03:34,900 Hemos elegido w en este caso porque queremos escribir en el archivo. 65 00:03:34,900 --> 00:03:38,820 R, como usted probablemente puede adivinar, es para leer el archivo. 66 00:03:38,820 --> 00:03:41,760 Y una es para anexar al archivo. 67 00:03:41,760 --> 00:03:44,960 Mientras tanto w y una puede ser utilizado para escribir en archivos, 68 00:03:44,960 --> 00:03:47,460 w comenzará a escribir desde el principio del archivo 69 00:03:47,460 --> 00:03:50,810 y potencialmente sobrescribir los datos que han sido previamente almacenados. 70 00:03:50,810 --> 00:03:54,070 De forma predeterminada, el archivo se abrirá si no existe ya, 71 00:03:54,070 --> 00:03:57,180 se crea en nuestro directorio de trabajo actual. 72 00:03:57,180 --> 00:04:00,540 Sin embargo, si queremos acceder o crear un archivo en una ubicación diferente, 73 00:04:00,540 --> 00:04:02,650 en el primer argumento de fopen, 74 00:04:02,650 --> 00:04:05,840 es posible especificar una ruta de archivo en adición al nombre de archivo. 75 00:04:05,840 --> 00:04:09,490 Mientras que la primera parte de este proceso es sólo una línea de código largo, 76 00:04:09,490 --> 00:04:12,350 que siempre es una buena práctica incluir otra serie de líneas 77 00:04:12,350 --> 00:04:15,930 El registro de entrada para asegurarse de que el archivo se ha abierto correctamente o creado. 78 00:04:15,930 --> 00:04:20,300 Si fopen devuelve un valor nulo, no queremos seguir adelante con nuestro programa, 79 00:04:20,300 --> 00:04:23,270 y esto puede ocurrir si el sistema operativo no tiene memoria 80 00:04:23,270 --> 00:04:27,940 o si intenta abrir un archivo en un directorio para el que no contaba con los permisos adecuados. 81 00:04:27,940 --> 00:04:31,780 >> La segunda parte del proceso se realiza en bucle mientras que la máquina de escribir. 82 00:04:31,780 --> 00:04:35,000 Nosotros usamos una función de biblioteca CS50 para obtener entrada del usuario, 83 00:04:35,000 --> 00:04:37,190 y asumiendo que no desea salir del programa, 84 00:04:37,190 --> 00:04:41,940 usamos los fputs función para tomar la cadena y escribirla en el archivo. 85 00:04:41,940 --> 00:04:46,700 fputs es sólo una de las muchas funciones que podría utilizar para escribir en el archivo. 86 00:04:46,700 --> 00:04:51,920 Otros incluyen fwrite, fputc y fprintf incluso. 87 00:04:51,920 --> 00:04:54,840 Independientemente de la función particular que terminan usando, sin embargo, 88 00:04:54,840 --> 00:04:57,480 todos ellos necesitan saber, a través de sus argumentos, 89 00:04:57,480 --> 00:04:59,670 por lo menos dos cosas - 90 00:04:59,670 --> 00:05:03,140 lo que tiene que ser por escrito y en el que hay que escribir. 91 00:05:03,140 --> 00:05:07,240 En nuestro caso, la entrada es la cadena que necesita ser escrita 92 00:05:07,240 --> 00:05:11,290 y fp es el puntero que nos lleva a donde estamos escribiendo. 93 00:05:11,290 --> 00:05:15,330 En este programa, la segunda parte del proceso es bastante sencillo. 94 00:05:15,330 --> 00:05:17,360 Simplemente estamos tomando una cadena del usuario 95 00:05:17,360 --> 00:05:22,120 y añadir directamente a nuestro archivo con poca o ninguna validación de entrada o controles de seguridad. 96 00:05:22,120 --> 00:05:26,160 A menudo, sin embargo, la segunda parte se ocupará de la mayor parte de su código. 97 00:05:26,160 --> 00:05:30,580 Por último, la tercera parte está en la línea 58, donde se cierra el archivo. 98 00:05:30,580 --> 00:05:34,860 Aquí llamamos fclose y pasarlo nuestro apuntador de archivo original. 99 00:05:34,860 --> 00:05:39,500 En la línea siguiente, volvemos a cero, lo que indica el final de nuestro programa. 100 00:05:39,500 --> 00:05:42,630 Y, sí, la tercera parte es tan simple como eso. 101 00:05:42,630 --> 00:05:45,260 >> Vamos a pasar a la lectura de los archivos. 102 00:05:45,260 --> 00:05:48,220 De vuelta en nuestro directorio tenemos un archivo llamado printer.c. 103 00:05:48,220 --> 00:05:50,910 Vamos a correr con el archivo 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 su nombre indica, simplemente imprimir el contenido del archivo se le ha pasado. 106 00:05:58,150 --> 00:06:00,230 Y ahí lo tenemos. 107 00:06:00,230 --> 00:06:03,780 Las líneas de código que había escrito anteriormente y guardado en doc.txt. 108 00:06:03,780 --> 00:06:06,980 Hi. Mi nombre es Jason. 109 00:06:06,980 --> 00:06:09,120 Si nos sumergimos en printer.c, 110 00:06:09,120 --> 00:06:13,570 vemos que una gran parte del código es similar a lo que puedes ir andando a través de typewriter.c. 111 00:06:13,570 --> 00:06:16,720 De hecho la línea 22, donde abrimos el archivo, 112 00:06:16,720 --> 00:06:19,220 y la línea 39, donde se cerró el expediente, 113 00:06:19,220 --> 00:06:23,890 son casi idénticos a typewriter.c, con excepción de argumento fopen segundo. 114 00:06:23,890 --> 00:06:26,510 Esta vez estamos leyendo de un archivo, 115 00:06:26,510 --> 00:06:29,040 por lo que hemos elegido en lugar de r w. 116 00:06:29,040 --> 00:06:31,950 Por lo tanto, vamos a centrarnos en la segunda parte del proceso. 117 00:06:31,950 --> 00:06:36,060 En la línea 35, a la segunda condición en nuestro 4 loop, 118 00:06:36,060 --> 00:06:38,590 hacemos un llamado a fgets, 119 00:06:38,590 --> 00:06:42,190 la función fputs compañero de antes. 120 00:06:42,190 --> 00:06:44,660 En esta ocasión contamos con tres argumentos. 121 00:06:44,660 --> 00:06:48,810 El primero es el puntero a la matriz de caracteres en la que se almacena la cadena. 122 00:06:48,810 --> 00:06:52,670 El segundo es el número máximo de caracteres a leer. 123 00:06:52,670 --> 00:06:56,010 Y el tercero es el puntero al archivo con el que estamos trabajando. 124 00:06:56,010 --> 00:07:00,780 Se dará cuenta de que el bucle termina cuando fgets devuelve null. 125 00:07:00,780 --> 00:07:02,940 Hay dos razones que esto pudo haber sucedido. 126 00:07:02,940 --> 00:07:05,380 En primer lugar, un error puede haber ocurrido. 127 00:07:05,380 --> 00:07:10,740 En segundo lugar, y más probablemente, el final del archivo se alcanzó caracteres y no más leer fueron. 128 00:07:10,740 --> 00:07:14,040 En caso de que usted se esté preguntando, no existen dos funciones que nos permiten contar 129 00:07:14,040 --> 00:07:17,160 lo cual es la causa de este puntero nulo en particular. 130 00:07:17,160 --> 00:07:21,090 Y, como es lógico, ya que tienen que ver con trabajar con los archivos, 131 00:07:21,090 --> 00:07:26,940 tanto la función ferror y la función de arranque feof con la letra f. 132 00:07:26,940 --> 00:07:32,130 >> Por último, antes de concluir, una breve nota sobre el final de la función de archivo, 133 00:07:32,130 --> 00:07:36,690 que, como se acaba de mencionar, se escribe como feof. 134 00:07:36,690 --> 00:07:41,550 A menudo te encontrarás con bucles while y for a leer progresivamente su camino a través de los archivos. 135 00:07:41,550 --> 00:07:45,790 Por lo tanto, usted necesita una manera de poner fin a estos bucles después de llegar al final de estos archivos. 136 00:07:45,790 --> 00:07:50,510 Llamar a feof en el puntero del archivo y la comprobación para ver si es verdad 137 00:07:50,510 --> 00:07:52,310 haría exactamente eso. 138 00:07:52,310 --> 00:07:59,820 Por lo tanto, un bucle mientras la condición (! Feof (fp)) puede parecer una solución perfectamente adecuada. 139 00:07:59,820 --> 00:08:03,770 Sin embargo, digamos que tenemos una línea que queda en nuestro archivo de texto. 140 00:08:03,770 --> 00:08:07,130 Vamos a entrar en nuestro bucle while y todo saldrá según lo planeado. 141 00:08:07,130 --> 00:08:12,750 En la siguiente ronda a través de nuestro programa comprobará si feof de fp es cierto, 142 00:08:12,750 --> 00:08:15,430 pero - y éste es el punto crucial entender aquí - 143 00:08:15,430 --> 00:08:17,770 no va a ser verdad por el momento. 144 00:08:17,770 --> 00:08:21,110 Eso es porque el propósito de feof no es comprobar 145 00:08:21,110 --> 00:08:24,400 si la siguiente llamada a una función de lectura se pulsa el final del archivo, 146 00:08:24,400 --> 00:08:28,190 sino más bien para comprobar si o no el final del archivo ya se ha alcanzado. 147 00:08:28,190 --> 00:08:30,140 En el caso de este ejemplo, 148 00:08:30,140 --> 00:08:32,780 la lectura de la última línea de nuestro fichero va perfectamente sin problemas, 149 00:08:32,780 --> 00:08:36,210 pero el programa todavía no sabe que hemos alcanzado el final de nuestro archivo. 150 00:08:36,210 --> 00:08:40,549 No es hasta que lo haga una lectura adicional que contrarresta el final del archivo. 151 00:08:40,549 --> 00:08:43,210 Así, una condición correcta sería la siguiente: 152 00:08:43,210 --> 00:08:49,330 fgets y sus tres argumentos - de salida, tamaño de la producción, y FP - 153 00:08:49,330 --> 00:08:52,570 y todo eso no es igual a null. 154 00:08:52,570 --> 00:08:55,260 Este es el enfoque que adoptamos en printer.c, 155 00:08:55,260 --> 00:08:57,890 y en este caso, después de salir del bucle, 156 00:08:57,890 --> 00:09:04,290 usted puede llamar o feof ferror para informar al usuario sobre el razonamiento específico para salir de este bucle. 157 00:09:04,290 --> 00:09:08,100 >> Escritura y lectura de un archivo es, en su forma más básica, 158 00:09:08,100 --> 00:09:10,150 un simple proceso de 3 partes. 159 00:09:10,150 --> 00:09:12,530 En primer lugar, abrir el archivo. 160 00:09:12,530 --> 00:09:16,740 En segundo lugar, hemos puesto algunas cosas en nuestro archivo o tomar algunas cosas de ella. 161 00:09:16,740 --> 00:09:19,200 En tercer lugar, se cierra el archivo. 162 00:09:19,200 --> 00:09:21,170 Las partes primera y última son fáciles. 163 00:09:21,170 --> 00:09:23,920 La parte central es donde las cosas se encuentra delicado. 164 00:09:23,920 --> 00:09:27,760 Y aunque por debajo de la capucha que siempre estamos tratando con una larga secuencia de ceros y unos, 165 00:09:27,760 --> 00:09:30,710 sí ayuda al codificar para añadir una capa de abstracción 166 00:09:30,710 --> 00:09:35,350 que convierte la secuencia en algo que se parece más a lo que estamos acostumbrados a ver. 167 00:09:35,350 --> 00:09:39,570 Por ejemplo, si estamos trabajando con un archivo de mapa de bits de 24-bit, 168 00:09:39,570 --> 00:09:43,290 que probablemente va a leer o escribir tres bytes a la vez. 169 00:09:43,290 --> 00:09:46,450 En ese caso, tendría sentido para definir y nombrar apropiadamente 170 00:09:46,450 --> 00:09:48,980 una estructura que es de 3 bytes de gran tamaño. 171 00:09:48,980 --> 00:09:51,410 >> A pesar de trabajar con archivos puede parecer complicado, 172 00:09:51,410 --> 00:09:54,530 la utilización de ellos nos permite hacer algo verdaderamente notable. 173 00:09:54,530 --> 00:09:58,880 Podemos cambiar el estado del mundo fuera de nuestro programa, 174 00:09:58,880 --> 00:10:01,730 podemos crear algo que vive más allá de la vida de nuestro programa, 175 00:10:01,730 --> 00:10:07,190 o incluso podemos cambiar algo que se creó antes de que nuestro programa comenzó a correr. 176 00:10:07,190 --> 00:10:11,210 Interactuar con los archivos es una parte realmente de gran alcance de la programación en C. 177 00:10:11,210 --> 00:10:15,300 y estoy emocionado de ver lo que vamos a crear con ella en el código por venir. 178 00:10:15,300 --> 00:10:19,770 Mi nombre es Jason Hirschhorn. Esto es 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 Bien. Una sola toma. Aquí vamos. 182 00:10:49,000 --> 00:10:52,140 Cuando pensamos en un archivo - >> Oh, espera. Lo siento. 183 00:10:52,140 --> 00:10:56,800 [Risas] Bueno. 184 00:11:06,620 --> 00:11:09,970 Hey there. 185 00:11:13,670 --> 00:11:16,310 Cuando pensamos en un archivo - 186 00:11:17,610 --> 00:11:20,710 Cuando usted piensa en un archivo - De acuerdo. Dime cuando estés listo. 187 00:11:20,710 --> 00:11:22,520 Oh, genial. 188 00:11:22,520 --> 00:11:26,180 Aunque la lectura de un teleprompter puede parecer - no. Mi mal.