1 00:00:00,000 --> 00:00:02,000 [Powered by Google Translate] [Fil I / O] 2 00:00:02,000 --> 00:00:04,000 [Jason Hirschhorn, Harvard University] 3 00:00:04,000 --> 00:00:07,000 [Dette er CS50, CS50.TV] 4 00:00:07,000 --> 00:00:11,000 Når vi tenker på en fil, kommer det til hjernen er et Microsoft Word-dokument, 5 00:00:11,000 --> 00:00:14,000 et JPEG-bilde, eller en MP3-sang, 6 00:00:14,000 --> 00:00:17,000 og vi samhandler med hver av disse typer filer på forskjellige måter. 7 00:00:17,000 --> 00:00:20,000 For eksempel, i et Word-dokument legger vi tekst 8 00:00:20,000 --> 00:00:24,000 mens med et JPEG-bilde kan vi beskjære kantene eller retusjere fargene. 9 00:00:24,000 --> 00:00:28,000 Likevel under panseret alle filene i datamaskinen vår er ingenting mer 10 00:00:28,000 --> 00:00:31,000 enn en lang sekvens av nuller og enere. 11 00:00:31,000 --> 00:00:33,000 Det er opp til den spesifikke applikasjonen som samhandler med filen 12 00:00:33,000 --> 00:00:38,000 å bestemme hvordan å behandle denne lange sekvensen og presentere det til brukeren. 13 00:00:38,000 --> 00:00:41,000 På den ene siden, kan et dokument se på bare en byte, 14 00:00:41,000 --> 00:00:45,000 eller 8 nuller og enere, og vise et ASCII-tegn på skjermen. 15 00:00:45,000 --> 00:00:48,000 På den annen side kan et punktgrafikkbilde se på 3 byte, 16 00:00:48,000 --> 00:00:50,000 eller 24 nuller og enere, 17 00:00:50,000 --> 00:00:53,000 og tolke dem som 3 heksadesimale tall 18 00:00:53,000 --> 00:00:56,000 som representerer verdiene for rød, grønn og blå 19 00:00:56,000 --> 00:00:58,000 i én piksel i et bilde. 20 00:00:58,000 --> 00:01:01,000 Uansett hva de kan se ut på skjermen, på sin kjernekompetanse, 21 00:01:01,000 --> 00:01:05,000 filene er noe mer enn en sekvens av nuller og enere. 22 00:01:05,000 --> 00:01:08,000 Så la oss dykke inn og se på hvordan vi faktisk manipulere disse nuller og enere 23 00:01:08,000 --> 00:01:12,000 når det gjelder å skrive til og lese fra en fil. 24 00:01:12,000 --> 00:01:15,000 >> Jeg vil starte med å bryte det ned i en enkel 3-stegs prosess. 25 00:01:15,000 --> 00:01:19,000 Deretter vil jeg dykke inn i to kode eksempler som viser disse tre delene. 26 00:01:19,000 --> 00:01:23,000 Til slutt vil jeg gå gjennom prosessen og noen av de viktigste detaljene. 27 00:01:23,000 --> 00:01:25,000 Som med hvilken som helst fil som sitter på skrivebordet ditt, 28 00:01:25,000 --> 00:01:28,000 den første tingen å gjøre er å åpne den. 29 00:01:28,000 --> 00:01:31,000 I C gjør vi dette ved å erklære en peker til en forhåndsdefinert struct 30 00:01:31,000 --> 00:01:33,000 som representerer en fil på disken. 31 00:01:33,000 --> 00:01:38,460 I denne funksjonen samtale, vi også bestemme om vi ønsker å skrive til eller lese fra filen. 32 00:01:38,460 --> 00:01:41,660 Deretter gjør vi selve lesing og skriving. 33 00:01:41,660 --> 00:01:44,800 Det finnes en rekke spesialiserte funksjoner vi kan bruke i denne delen, 34 00:01:44,800 --> 00:01:48,790 og nesten alle av dem starter med bokstaven F, som står for filen. 35 00:01:48,790 --> 00:01:53,560 Sist, beslektet med den lille røde X i det øverste hjørnet av filene åpnes på datamaskinen, 36 00:01:53,560 --> 00:01:56,680 vi lukke filen med en endelig funksjon samtale. 37 00:01:56,680 --> 00:01:59,540 Nå som vi har en generell ide om hva vi skal gjøre, 38 00:01:59,540 --> 00:02:02,000 la oss dykke inn koden. 39 00:02:02,000 --> 00:02:06,100 >> I denne katalogen har vi to C-filer og tilhørende kjørbare filer. 40 00:02:06,100 --> 00:02:09,710 Skrivemaskinen Programmet tar en kommandolinje argument, 41 00:02:09,710 --> 00:02:12,060 navnet på dokumentet vi ønsker å skape. 42 00:02:12,060 --> 00:02:16,160 I dette tilfellet vil vi kaller det doc.txt. 43 00:02:16,160 --> 00:02:19,080 La oss kjøre programmet og skriv et par linjer. 44 00:02:19,080 --> 00:02:23,660 Hei. Mitt navn er Jason. 45 00:02:23,660 --> 00:02:26,710 Til slutt vil vi tast "quit". 46 00:02:26,710 --> 00:02:29,720 Hvis vi nå liste opp alle filene i denne katalogen, 47 00:02:29,720 --> 00:02:33,770 Vi ser at et nytt dokument eksisterer kalt doc.txt. 48 00:02:34,190 --> 00:02:36,110 Det er filen dette programmet nettopp opprettet. 49 00:02:36,110 --> 00:02:40,520 Og selvfølgelig er det for noe mer enn en lang sekvens av nuller og enere. 50 00:02:41,100 --> 00:02:43,260 Hvis vi åpner denne nye filen, 51 00:02:43,260 --> 00:02:45,870 vi ser de 3 linjer med kode vi inngått programmet vårt - 52 00:02:46,060 --> 00:02:49,060 Hei. May heter Jason. 53 00:02:49,580 --> 00:02:52,090 Men hva som faktisk skjer når typewriter.c kjører? 54 00:02:52,810 --> 00:02:55,520 Den første linjen av interesse for oss er linje 24. 55 00:02:55,560 --> 00:02:58,490 I denne linjen, erklærer vi vår filpekeren. 56 00:02:59,080 --> 00:03:03,140 Funksjonen som returnerer denne pekeren, fopen, tar to argumenter. 57 00:03:03,140 --> 00:03:07,440 Den første er filnavnet inkludert filtypen hvis hensiktsmessig. 58 00:03:07,440 --> 00:03:10,980 Husker at en filtype ikke påvirker filen på sitt laveste nivå. 59 00:03:10,980 --> 00:03:14,640 Vi er alltid å gjøre med en lang sekvens av nuller og enere. 60 00:03:14,640 --> 00:03:19,630 Men det gjør påvirker hvordan filene tolkes og hvilke applikasjoner som brukes til å åpne dem. 61 00:03:19,630 --> 00:03:22,290 Det andre argumentet til fopen er en enkelt bokstav 62 00:03:22,290 --> 00:03:25,300 som står for det vi har tenkt å gjøre etter at vi åpner filen. 63 00:03:25,300 --> 00:03:30,630 Det er tre alternativer for dette argumentet - W, R og A. 64 00:03:30,630 --> 00:03:34,900 Vi har valgt w i dette tilfellet fordi vi ønsker å skrive til filen. 65 00:03:34,900 --> 00:03:38,820 R, som du kan sikkert gjette, er for lesing til filen. 66 00:03:38,820 --> 00:03:41,760 Og en er for føye til filen. 67 00:03:41,760 --> 00:03:44,960 Mens både W og en kan brukes for å skrive til filer, 68 00:03:44,960 --> 00:03:47,460 w vil begynne å skrive fra begynnelsen av filen 69 00:03:47,460 --> 00:03:50,810 og potensielt overskrive alle data som tidligere har blitt lagret. 70 00:03:50,810 --> 00:03:54,070 Som standard filen vi åpner, hvis det ikke allerede finnes, 71 00:03:54,070 --> 00:03:57,180 er skapt i vår nåværende arbeidskatalog. 72 00:03:57,180 --> 00:04:00,540 Men hvis vi ønsker å få tilgang til eller opprette en fil på et annet sted, 73 00:04:00,540 --> 00:04:02,650 i det første argumentet for fopen, 74 00:04:02,650 --> 00:04:05,840 Vi kan angi en filbane i tillegg til filnavnet. 75 00:04:05,840 --> 00:04:09,490 Mens den første delen av denne prosessen er bare en kodelinje lang, 76 00:04:09,490 --> 00:04:12,350 det er alltid god praksis å inkludere et annet sett av linjer 77 00:04:12,350 --> 00:04:15,930 som kontrollerer at filen var vellykket åpnet eller opprettet. 78 00:04:15,930 --> 00:04:20,300 Hvis fopen returnerer null, ville vi ikke ønsker å gå videre med vårt program, 79 00:04:20,300 --> 00:04:23,270 og dette kan skje hvis operativsystemet er ute av minne 80 00:04:23,270 --> 00:04:27,940 eller hvis vi prøver å åpne en fil i en katalog som vi ikke har de riktige tillatelsene. 81 00:04:27,940 --> 00:04:31,780 >> Del to av prosessen foregår i skrivemaskinenes mens loop. 82 00:04:31,780 --> 00:04:35,000 Vi bruker en CS50 bibliotek-funksjonen for å få innspill fra brukeren, 83 00:04:35,000 --> 00:04:37,190 og forutsatt at de ikke ønsker å avslutte programmet, 84 00:04:37,190 --> 00:04:41,940 vi bruker funksjonen fputs å ta strengen og skrive den til filen. 85 00:04:41,940 --> 00:04:46,700 fputs er bare ett av de mange funksjonene vi kan bruke til å skrive til filen. 86 00:04:46,700 --> 00:04:51,920 Andre inkluderer fwrite, fputc, og selv fprintf. 87 00:04:51,920 --> 00:04:54,840 Uavhengig av den bestemte funksjon ender vi opp med å bruke, selv om, 88 00:04:54,840 --> 00:04:57,480 alle av dem trenger å vite, via sine argumenter, 89 00:04:57,480 --> 00:04:59,670 minst to ting - 90 00:04:59,670 --> 00:05:03,140 hva som må skrives og hvor det er behov for å bli skrevet til. 91 00:05:03,140 --> 00:05:07,240 I vårt tilfelle, er input strengen som må skrives 92 00:05:07,240 --> 00:05:11,290 og fp er pekeren som leder oss til der vi skriver. 93 00:05:11,290 --> 00:05:15,330 I dette programmet, er del to av prosessen ganske grei. 94 00:05:15,330 --> 00:05:17,360 Vi er rett og slett å ta en streng fra brukeren 95 00:05:17,360 --> 00:05:22,120 og legge det direkte til file vår med lite til ingen validering av inndata eller sikkerhetskontroller. 96 00:05:22,120 --> 00:05:26,160 Ofte vil imidlertid del to ta opp mesteparten av koden. 97 00:05:26,160 --> 00:05:30,580 Endelig er del tre på linje 58, der vi lukke filen. 98 00:05:30,580 --> 00:05:34,860 Her kaller vi fclose og gi det vår opprinnelige filen pekeren. 99 00:05:34,860 --> 00:05:39,500 I den påfølgende linjen, går vi tilbake null, signaliserte slutten av programmet vårt. 100 00:05:39,500 --> 00:05:42,630 Og, ja, er del tre så enkelt som det. 101 00:05:42,630 --> 00:05:45,260 >> La oss gå videre til å lese fra filer. 102 00:05:45,260 --> 00:05:48,220 Tilbake i katalogen vår har vi en fil som heter printer.c. 103 00:05:48,220 --> 00:05:50,910 La oss kjøre det med filen vi nettopp opprettet - 104 00:05:50,910 --> 00:05:53,350 doc.txt. 105 00:05:53,350 --> 00:05:58,150 Dette programmet, som navnet antyder, vil bare skrive ut innholdet i filen sendes til den. 106 00:05:58,150 --> 00:06:00,230 Og der har vi det. 107 00:06:00,230 --> 00:06:03,780 Linjene med kode vi hadde skrevet tidligere og lagret i doc.txt. 108 00:06:03,780 --> 00:06:06,980 Hei. Mitt navn er Jason. 109 00:06:06,980 --> 00:06:09,120 Hvis vi dykke inn printer.c, 110 00:06:09,120 --> 00:06:13,570 vi ser at mye av koden ligner det vi bare gikk gjennom i typewriter.c. 111 00:06:13,570 --> 00:06:16,720 Faktisk linje 22, der vi åpnet filen, 112 00:06:16,720 --> 00:06:19,220 og 39 linjer, der vi lukket filen, 113 00:06:19,220 --> 00:06:23,890 er begge nesten identisk med typewriter.c, lagre for fopen andre argumentet. 114 00:06:23,890 --> 00:06:26,510 Denne gangen vi leser fra en fil, 115 00:06:26,510 --> 00:06:29,040 så vi har valgt r istedenfor w. 116 00:06:29,040 --> 00:06:31,950 Således, la oss fokusere på den andre delen av prosessen. 117 00:06:31,950 --> 00:06:36,060 I linje 35, som den andre tilstand i våre 4 løkke, 118 00:06:36,060 --> 00:06:38,590 vi gjør et kall til fgets, 119 00:06:38,590 --> 00:06:42,190 følgesvenn funksjonen til fputs fra før. 120 00:06:42,190 --> 00:06:44,660 Denne gangen har vi tre argumenter. 121 00:06:44,660 --> 00:06:48,810 Den første er pekeren til rekken av tegn der strengen skal lagres. 122 00:06:48,810 --> 00:06:52,670 Den andre er det maksimale antall tegn som skal leses. 123 00:06:52,670 --> 00:06:56,010 Og den tredje er pekeren til filen som vi jobber. 124 00:06:56,010 --> 00:07:00,780 Du vil merke at for loop slutter når fgets returnerer null. 125 00:07:00,780 --> 00:07:02,940 Det er to grunnen til at dette kan ha skjedd. 126 00:07:02,940 --> 00:07:05,380 Først, kan en feil har oppstått. 127 00:07:05,380 --> 00:07:10,740 Sekund, og mer sannsynlig, slutten av filen nådd og ingen flere tegn ble lest. 128 00:07:10,740 --> 00:07:14,040 I tilfelle du lurer, finnes to funksjoner gjør at tillate oss å fortelle 129 00:07:14,040 --> 00:07:17,160 som grunn er årsaken til denne spesielle nullpeker. 130 00:07:17,160 --> 00:07:21,090 Og, ikke overraskende, siden de har å gjøre med å jobbe med filer, 131 00:07:21,090 --> 00:07:26,940 både fError funksjonen og feof funksjonen start med bokstaven f. 132 00:07:26,940 --> 00:07:32,130 >> Til slutt, før vi konkluderer, en rask kommentar om slutten av filen funksjon, 133 00:07:32,130 --> 00:07:36,690 som, som nevnt tidligere, er skrevet som feof. 134 00:07:36,690 --> 00:07:41,550 Ofte vil du finne deg selv ved hjelp stund og etter looper å gradvis lese deg gjennom filer. 135 00:07:41,550 --> 00:07:45,790 Dermed trenger du en måte å avslutte disse loopene når du kommer til slutten av disse filene. 136 00:07:45,790 --> 00:07:50,510 Ringe feof på filpekeren og sjekke for å se om det er sant 137 00:07:50,510 --> 00:07:52,310 ville gjøre nettopp det. 138 00:07:52,310 --> 00:07:59,820 Dermed kan en stund loop med tilstanden (! Feof (fp)) virke som en helt riktig løsning. 139 00:07:59,820 --> 00:08:03,770 Men si at vi har én linje igjen i vår tekstfil. 140 00:08:03,770 --> 00:08:07,130 Vi vil delta i vår mens loop og alt vil fungere som planlagt. 141 00:08:07,130 --> 00:08:12,750 På neste runde gjennom, vil vårt program for å se om feof av fp er sant, 142 00:08:12,750 --> 00:08:15,430 men - og dette er det avgjørende punktet å forstå her - 143 00:08:15,430 --> 00:08:17,770 det vil ikke være sant ennå. 144 00:08:17,770 --> 00:08:21,110 Det er fordi den hensikt feof er ikke å kontrollere 145 00:08:21,110 --> 00:08:24,400 hvis neste samtale til et Lesefunksjonen vil treffe enden av filen, 146 00:08:24,400 --> 00:08:28,190 men heller å sjekke hvorvidt slutten av filen er allerede nådd. 147 00:08:28,190 --> 00:08:30,140 I tilfelle av dette eksemplet, 148 00:08:30,140 --> 00:08:32,780 leser den siste linjen av filen vår går helt knirkefritt, 149 00:08:32,780 --> 00:08:36,210 men programmet ennå ikke vet at vi har truffet slutten av filen vår. 150 00:08:36,210 --> 00:08:40,549 Det er ikke før det gjør en ekstra lest at det motvirker slutten av filen. 151 00:08:40,549 --> 00:08:43,210 Dermed vil en korrekt tilstand være følgende: 152 00:08:43,210 --> 00:08:49,330 fgets og sine tre argumenter - utgang, størrelsen på produksjonen, og fp - 153 00:08:49,330 --> 00:08:52,570 og alle som ikke lik null. 154 00:08:52,570 --> 00:08:55,260 Dette er den tilnærmingen vi tok i printer.c, 155 00:08:55,260 --> 00:08:57,890 og i dette tilfellet, etter løkken kommer ut, 156 00:08:57,890 --> 00:09:04,290 du kan kalle feof eller fError å informere brukeren om den spesifikke begrunnelsen for spennende denne sløyfen. 157 00:09:04,290 --> 00:09:08,100 >> Skriving til og lesing fra en fil er, på sitt mest grunnleggende, 158 00:09:08,100 --> 00:09:10,150 en enkel 3-stegs prosess. 159 00:09:10,150 --> 00:09:12,530 Først åpner vi filen. 160 00:09:12,530 --> 00:09:16,740 Sekund, setter vi noen ting inn i filen vår, eller ta noen ting ut av det. 161 00:09:16,740 --> 00:09:19,200 Tredje, lukker vi filen. 162 00:09:19,200 --> 00:09:21,170 Første og siste deler er lette. 163 00:09:21,170 --> 00:09:23,920 Den midtre delen er der det vanskelige ting ligger. 164 00:09:23,920 --> 00:09:27,760 Og selv om under panseret vi alltid arbeider med en lang sekvens av nuller og enere, 165 00:09:27,760 --> 00:09:30,710 det hjelper når koding for å legge et lag av abstraksjon 166 00:09:30,710 --> 00:09:35,350 som gjør sekvensen til noe som mer ligner det vi er vant til å se. 167 00:09:35,350 --> 00:09:39,570 For eksempel, hvis vi jobber med en 24-bit bitmap fil, 168 00:09:39,570 --> 00:09:43,290 Vi vil sannsynligvis være å lese eller skrive tre byte om gangen. 169 00:09:43,290 --> 00:09:46,450 I så fall ville det være fornuftig å definere og hensiktsmessig navn 170 00:09:46,450 --> 00:09:48,980 en struct som er 3 byte stor. 171 00:09:48,980 --> 00:09:51,410 >> Selv arbeider med filer kan virke komplisert, 172 00:09:51,410 --> 00:09:54,530 utnytte dem tillater oss å gjøre noe virkelig bemerkelsesverdig. 173 00:09:54,530 --> 00:09:58,880 Vi kan endre tilstanden i verden utenfor vårt program, 174 00:09:58,880 --> 00:10:01,730 vi kan skape noe som lever utover liv i vårt program, 175 00:10:01,730 --> 00:10:07,190 eller vi kan selv endre noe som ble opprettet før vårt program startet. 176 00:10:07,190 --> 00:10:11,210 Samhandle med filene er en virkelig kraftig del av programmering i C. 177 00:10:11,210 --> 00:10:15,300 og jeg gleder meg til å se hva du kommer til å lage med det i koden som kommer. 178 00:10:15,300 --> 00:10:19,770 Mitt navn er Jason Hirschhorn. Dette er CS50. 179 00:10:19,770 --> 00:10:21,770 [CS50.TV] 180 00:10:21,770 --> 00:10:25,940 >> [Latter] 181 00:10:25,940 --> 00:10:29,330 Okay. Man ta. Here we go. 182 00:10:49,000 --> 00:10:52,140 Når vi tenker på en fil - >> Å, vent. Unnskyld. 183 00:10:52,140 --> 00:10:56,800 [Latter] Okay. 184 00:11:06,620 --> 00:11:09,970 Hei der. 185 00:11:13,670 --> 00:11:16,310 Når vi tenker på en fil - 186 00:11:17,610 --> 00:11:20,710 Når du tenker på en fil - Ok. Fortell meg når du er klar. 187 00:11:20,710 --> 00:11:22,520 Flott. 188 00:11:22,520 --> 00:11:26,180 Selv leser fra en sufflør kan virke - ingen. Min feil.