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 [Detta är CS50, CS50.TV] 4 00:00:07,000 --> 00:00:11,000 När vi tänker på en fil, vad kommer att tänka på är ett Microsoft Word-dokument, 5 00:00:11,000 --> 00:00:14,000 en JPEG-bild eller en MP3-låt, 6 00:00:14,000 --> 00:00:17,000 och vi interagerar med var och en av dessa typer av filer på olika sätt. 7 00:00:17,000 --> 00:00:20,000 Till exempel i ett Word-dokument som vi lägger till text 8 00:00:20,000 --> 00:00:24,000 medan en JPEG-bild kan vi skära bort kanterna eller retuschera färger. 9 00:00:24,000 --> 00:00:28,000 Men under huven alla filer i vår dator är inget annat 10 00:00:28,000 --> 00:00:31,000 än en lång sekvens av nollor och ettor. 11 00:00:31,000 --> 00:00:33,000 Det är upp till de specifika program som interagerar med filen 12 00:00:33,000 --> 00:00:38,000 att besluta om hur att behandla denna långa sekvens och presentera det för användaren. 13 00:00:38,000 --> 00:00:41,000 Å ena sidan kan ett dokument titta på endast en byte, 14 00:00:41,000 --> 00:00:45,000 eller 8 nollor och ettor och visa ett ASCII-tecken på skärmen. 15 00:00:45,000 --> 00:00:48,000 Å andra sidan kan en bitmappsbild titta på tre bitgrupper, 16 00:00:48,000 --> 00:00:50,000 eller 24 nollor och ettor, 17 00:00:50,000 --> 00:00:53,000 och tolka dem som 3 hexadecimala tal 18 00:00:53,000 --> 00:00:56,000 som representerar värdena för röd, grön och blå 19 00:00:56,000 --> 00:00:58,000 i en pixel av en bild. 20 00:00:58,000 --> 00:01:01,000 Vad de kan se ut på skärmen, i sin kärna, 21 00:01:01,000 --> 00:01:05,000 filer är inget annat än en sekvens av nollor och ettor. 22 00:01:05,000 --> 00:01:08,000 Så låt oss dyka in och titta på hur vi faktiskt manipulera dessa nollor och ettor 23 00:01:08,000 --> 00:01:12,000 när det gäller att skriva till och läsa från en fil. 24 00:01:12,000 --> 00:01:15,000 >> Jag ska börja med att bryta ner det i en enkel 3-delad process. 25 00:01:15,000 --> 00:01:19,000 Nu ska jag dyka in två kodexempel som visar dessa tre delar. 26 00:01:19,000 --> 00:01:23,000 Slutligen kommer jag granska processen och några av dess viktigaste uppgifter. 27 00:01:23,000 --> 00:01:25,000 Som med alla filer som sitter på skrivbordet, 28 00:01:25,000 --> 00:01:28,000 det första du ska göra är att öppna den. 29 00:01:28,000 --> 00:01:31,000 I C vi gör detta genom att deklarera en pekare till en fördefinierad struktur 30 00:01:31,000 --> 00:01:33,000 som representerar en fil på hårddisken. 31 00:01:33,000 --> 00:01:38,460 I denna funktion samtalet bestämmer vi också om vi vill skriva till eller läsa från filen. 32 00:01:38,460 --> 00:01:41,660 Därefter gör vi själva läsning och skrivning. 33 00:01:41,660 --> 00:01:44,800 Det finns ett antal specialiserade funktioner vi kan använda i denna del, 34 00:01:44,800 --> 00:01:48,790 och nästan alla av dem börjar med bokstaven F, som står för fil. 35 00:01:48,790 --> 00:01:53,560 Senast, besläktad med de små röda X i det övre hörnet av filerna öppnas på din dator, 36 00:01:53,560 --> 00:01:56,680 Vi stänger filen med en slutlig funktionsanrop. 37 00:01:56,680 --> 00:01:59,540 Nu när vi har en allmän uppfattning om vad vi ska göra, 38 00:01:59,540 --> 00:02:02,000 låt oss dyka in koden. 39 00:02:02,000 --> 00:02:06,100 >> I denna katalog har vi två C-filer och deras motsvarande körbara filer. 40 00:02:06,100 --> 00:02:09,710 Skrivmaskinen programmet tar ett argument kommandoraden, 41 00:02:09,710 --> 00:02:12,060 namnet på det dokument som vi vill skapa. 42 00:02:12,060 --> 00:02:16,160 I det här fallet kommer vi kallar det doc.txt. 43 00:02:16,160 --> 00:02:19,080 Låt oss köra programmet och ange ett par rader. 44 00:02:19,080 --> 00:02:23,660 Hej. Mitt namn är Jason. 45 00:02:23,660 --> 00:02:26,710 Slutligen kommer vi att skriva "quit". 46 00:02:26,710 --> 00:02:29,720 Om vi ​​listar nu alla filer i den här katalogen, 47 00:02:29,720 --> 00:02:33,770 ser vi att ett nytt dokument existerar kallas doc.txt. 48 00:02:34,190 --> 00:02:36,110 Det är filen programmet nyss skapade. 49 00:02:36,110 --> 00:02:40,520 Och naturligtvis, är det också ingenting mer än en lång sekvens av nollor och ettor. 50 00:02:41,100 --> 00:02:43,260 Om vi ​​öppnar den nya filen, 51 00:02:43,260 --> 00:02:45,870 Vi ser 3 rader kod vi in ​​i vårt program - 52 00:02:46,060 --> 00:02:49,060 Hej. Maj namn är Jason. 53 00:02:49,580 --> 00:02:52,090 Men vad är egentligen händer när typewriter.c körs? 54 00:02:52,810 --> 00:02:55,520 Den första raden av intresse för oss är linje 24. 55 00:02:55,560 --> 00:02:58,490 I denna linje, förklarar vi vår fil pekare. 56 00:02:59,080 --> 00:03:03,140 Den funktion som returnerar denna pekare, fopen tar två argument. 57 00:03:03,140 --> 00:03:07,440 Den första är filnamnet, inklusive filnamnstillägget vid behov. 58 00:03:07,440 --> 00:03:10,980 Minns att ett filnamnstillägg inte påverkar filen på sin lägsta nivå. 59 00:03:10,980 --> 00:03:14,640 Vi är alltid att göra med en lång sekvens av nollor och ettor. 60 00:03:14,640 --> 00:03:19,630 Men det påverkar hur filer tolkas och vilka applikationer som används för att öppna dem. 61 00:03:19,630 --> 00:03:22,290 Det andra argumentet till fopen är en enda bokstav 62 00:03:22,290 --> 00:03:25,300 som står för vad vi planerar att göra efter att vi öppnar filen. 63 00:03:25,300 --> 00:03:30,630 Det finns tre alternativ för detta argument - W, R och A. 64 00:03:30,630 --> 00:03:34,900 Vi har valt w i detta fall eftersom vi vill skriva till filen. 65 00:03:34,900 --> 00:03:38,820 R, som ni säkert kan gissa, är för att läsa till filen. 66 00:03:38,820 --> 00:03:41,760 Och en är att lägga till filen. 67 00:03:41,760 --> 00:03:44,960 Medan både v och en kan användas för att skriva till filer, 68 00:03:44,960 --> 00:03:47,460 W kommer börja skriva från början av filen 69 00:03:47,460 --> 00:03:50,810 och potentiellt skriva över data som tidigare har lagrats. 70 00:03:50,810 --> 00:03:54,070 Som standard filen vi öppna, om det inte redan finns, 71 00:03:54,070 --> 00:03:57,180 skapas i vår nuvarande arbetskatalog. 72 00:03:57,180 --> 00:04:00,540 Men om vi vill komma åt eller skapa en fil på en annan plats, 73 00:04:00,540 --> 00:04:02,650 i det första argumentet i fopen, 74 00:04:02,650 --> 00:04:05,840 Vi kan ange en sökväg förutom filnamnet. 75 00:04:05,840 --> 00:04:09,490 Medan den första delen av denna process är bara en kodrad lång, 76 00:04:09,490 --> 00:04:12,350 det är alltid bra att inkludera en annan uppsättning linjer 77 00:04:12,350 --> 00:04:15,930 som kontrollerar att filen framgångsrikt öppnat eller skapat. 78 00:04:15,930 --> 00:04:20,300 Om fopen returnerar null, vill vi inte att gå vidare med vårt program, 79 00:04:20,300 --> 00:04:23,270 och detta kan hända om operativsystemet är slut på minne 80 00:04:23,270 --> 00:04:27,940 eller om vi försöker öppna en fil i en katalog som vi inte har rätt behörighet. 81 00:04:27,940 --> 00:04:31,780 >> Del två i processen sker i skrivmaskin är while-slinga. 82 00:04:31,780 --> 00:04:35,000 Vi använder en CS50 bibliotek funktion för att få input från användaren, 83 00:04:35,000 --> 00:04:37,190 och förutsatt att de inte vill avsluta programmet, 84 00:04:37,190 --> 00:04:41,940 Vi använder funktionen fputs att ta strängen och skriva till filen. 85 00:04:41,940 --> 00:04:46,700 fputs är bara en av de många funktioner som vi kan använda för att skriva till filen. 86 00:04:46,700 --> 00:04:51,920 Andra inkluderar fwrite, fputc och även fprintf. 87 00:04:51,920 --> 00:04:54,840 Oavsett den särskilda funktion vi sluta använda, men 88 00:04:54,840 --> 00:04:57,480 alla av dem behöver veta, via sina argument, 89 00:04:57,480 --> 00:04:59,670 minst två saker - 90 00:04:59,670 --> 00:05:03,140 vad som behöver skrivas och där den måste skrivas till. 91 00:05:03,140 --> 00:05:07,240 I vårt fall, matas den sträng som behöver skrivas 92 00:05:07,240 --> 00:05:11,290 och FP är pekaren som leder oss dit vi skriver. 93 00:05:11,290 --> 00:05:15,330 I detta program ingår två i processen ganska enkelt. 94 00:05:15,330 --> 00:05:17,360 Vi helt enkelt ta en sträng från användaren 95 00:05:17,360 --> 00:05:22,120 och lägga den direkt till vår fil med lite till ingen indatavalidering eller säkerhetskontroller. 96 00:05:22,120 --> 00:05:26,160 Men ofta kommer en del två tar upp den största delen av din kod. 97 00:05:26,160 --> 00:05:30,580 Slutligen är del tre i rad 58, där vi stänger filen. 98 00:05:30,580 --> 00:05:34,860 Här kallar vi fclose och ge det vårt ursprungliga filen pekare. 99 00:05:34,860 --> 00:05:39,500 I den efterföljande raden återvänder vi noll, vilket signalerar slutet på vårt program. 100 00:05:39,500 --> 00:05:42,630 Och, ja, en del tre så enkelt är det. 101 00:05:42,630 --> 00:05:45,260 >> Låt oss gå vidare till att läsa från filer. 102 00:05:45,260 --> 00:05:48,220 Tillbaka i vår katalog har vi en fil som heter printer.c. 103 00:05:48,220 --> 00:05:50,910 Vi kör den med filen vi just skapat - 104 00:05:50,910 --> 00:05:53,350 doc.txt. 105 00:05:53,350 --> 00:05:58,150 Detta program, som namnet antyder, helt enkelt skriva ut innehållet i filen skickas till den. 106 00:05:58,150 --> 00:06:00,230 Och där har vi det. 107 00:06:00,230 --> 00:06:03,780 De kodrader vi hade skrivit tidigare och sparas i doc.txt. 108 00:06:03,780 --> 00:06:06,980 Hej. Mitt namn är Jason. 109 00:06:06,980 --> 00:06:09,120 Om vi ​​dyker in printer.c, 110 00:06:09,120 --> 00:06:13,570 ser vi att mycket av koden liknar det vi bara gick igenom i typewriter.c. 111 00:06:13,570 --> 00:06:16,720 Faktum linje 22, där vi öppnade filen, 112 00:06:16,720 --> 00:06:19,220 och linje 39, där vi stängt filen, 113 00:06:19,220 --> 00:06:23,890 är båda nästan identiskt med typewriter.c, med undantag för fopen andra argumentet. 114 00:06:23,890 --> 00:06:26,510 Denna gång vi läser från en fil, 115 00:06:26,510 --> 00:06:29,040 så vi har valt r istället för w. 116 00:06:29,040 --> 00:06:31,950 Således, låt oss fokusera på den andra delen av processen. 117 00:06:31,950 --> 00:06:36,060 I linje 35, som det andra villkoret i vår 4 slinga, 118 00:06:36,060 --> 00:06:38,590 Vi ringer till fgets, 119 00:06:38,590 --> 00:06:42,190 följeslagare funktionen fputs från förr. 120 00:06:42,190 --> 00:06:44,660 Den här gången har vi tre argument. 121 00:06:44,660 --> 00:06:48,810 Den första är pekaren till gruppen av tecken där strängen kommer att lagras. 122 00:06:48,810 --> 00:06:52,670 Den andra är det maximala antalet tecken som ska läsas. 123 00:06:52,670 --> 00:06:56,010 Och den tredje är pekaren till filen som vi jobbar. 124 00:06:56,010 --> 00:07:00,780 Du kommer att märka att for-slingan avslutas när fgets returnerar null. 125 00:07:00,780 --> 00:07:02,940 Det finns två skäl till att det kan ha hänt. 126 00:07:02,940 --> 00:07:05,380 Först kan ett fel ha inträffat. 127 00:07:05,380 --> 00:07:10,740 Andra, och mer troligt var slutet av filen nås och inga fler tecken lästes. 128 00:07:10,740 --> 00:07:14,040 I fall du undrar, existerar två funktioner som gör att vi kan berätta 129 00:07:14,040 --> 00:07:17,160 varför är orsaken till denna null pekare. 130 00:07:17,160 --> 00:07:21,090 Och inte överraskande, eftersom de har att göra med att arbeta med filer, 131 00:07:21,090 --> 00:07:26,940 både ferror funktionen och feof funktionen börjar med bokstaven f.. 132 00:07:26,940 --> 00:07:32,130 >> Slutligen, innan vi avslutar, en snabb anteckning om slutet av filen funktion, 133 00:07:32,130 --> 00:07:36,690 vilket som just nämnts, skrivs som feof. 134 00:07:36,690 --> 00:07:41,550 Ofta hittar du dig själv med hjälp tag och för slingor att successivt läsa dig igenom filer. 135 00:07:41,550 --> 00:07:45,790 Därför behöver du ett sätt att avsluta dessa slingor när du når slutet av dessa filer. 136 00:07:45,790 --> 00:07:50,510 Ringa feof på filen pekaren och kontrollera om det är sant 137 00:07:50,510 --> 00:07:52,310 skulle göra just det. 138 00:07:52,310 --> 00:07:59,820 Således kan en while-slinga med villkoret (! Feof (fp)) verka som en perfekt lämplig lösning. 139 00:07:59,820 --> 00:08:03,770 Men säger att vi har en rad kvar i vår textfil. 140 00:08:03,770 --> 00:08:07,130 Vi kommer in i vår while-slinga och allt kommer att fungera som planerat. 141 00:08:07,130 --> 00:08:12,750 På nästa omgång igenom kommer vårt program att se om feof av fp är sant, 142 00:08:12,750 --> 00:08:15,430 men - och detta är den avgörande punkten att förstå här - 143 00:08:15,430 --> 00:08:17,770 det kommer inte vara sant ännu. 144 00:08:17,770 --> 00:08:21,110 Det beror på att syftet med feof är inte att kontrollera 145 00:08:21,110 --> 00:08:24,400 om nästa samtal till en läs funktion kommer att drabba slutet av filen, 146 00:08:24,400 --> 00:08:28,190 utan snarare att kontrollera huruvida eller inte slutet av filen redan har nåtts. 147 00:08:28,190 --> 00:08:30,140 I fallet med detta exempel, 148 00:08:30,140 --> 00:08:32,780 läser den sista raden i vår fil går perfekt smidigt, 149 00:08:32,780 --> 00:08:36,210 men programmet inte vet ännu att vi har drabbats slutet av vår fil. 150 00:08:36,210 --> 00:08:40,549 Det är inte förrän den gör en ytterligare läst att det motverkar slutet av filen. 151 00:08:40,549 --> 00:08:43,210 Sålunda skulle en korrekt tillstånd vara följande: 152 00:08:43,210 --> 00:08:49,330 fgets och dess tre argument - utgång, storlek utgång, och FP - 153 00:08:49,330 --> 00:08:52,570 och allt detta inte är lika med noll. 154 00:08:52,570 --> 00:08:55,260 Detta är den strategi som vi tog i printer.c, 155 00:08:55,260 --> 00:08:57,890 och i detta fall, efter avslutas slingan, 156 00:08:57,890 --> 00:09:04,290 Du kan kalla feof eller ferror att informera användaren om den specifika resonemang för att lämna denna slinga. 157 00:09:04,290 --> 00:09:08,100 >> Skriva till och läsa från en fil är i sin mest grundläggande, 158 00:09:08,100 --> 00:09:10,150 en enkel 3-delad processen. 159 00:09:10,150 --> 00:09:12,530 Först öppnar vi filen. 160 00:09:12,530 --> 00:09:16,740 Andra sätter vi vissa saker i vår fil eller ta vissa saker av det. 161 00:09:16,740 --> 00:09:19,200 Tredje, stänger vi ärendet. 162 00:09:19,200 --> 00:09:21,170 Den första och sista delar är lätt. 163 00:09:21,170 --> 00:09:23,920 Den mellersta delen är där knepiga grejer ligger. 164 00:09:23,920 --> 00:09:27,760 Och även under huven vi alltid att göra med en lång sekvens av nollor och ettor, 165 00:09:27,760 --> 00:09:30,710 det hjälper vid kodning att lägga ett lager av abstraktion 166 00:09:30,710 --> 00:09:35,350 som förvandlar den sekvens till något som mer liknar vad vi är vana att se. 167 00:09:35,350 --> 00:09:39,570 Till exempel, om vi arbetar med en 24-bitars bitmappsfil, 168 00:09:39,570 --> 00:09:43,290 vi kommer sannolikt att läsa eller skriva tre byte åt gången. 169 00:09:43,290 --> 00:09:46,450 I vilket fall skulle det vara meningsfullt att definiera och korrekt namn 170 00:09:46,450 --> 00:09:48,980 en struktur som är 3 byte stor. 171 00:09:48,980 --> 00:09:51,410 >> Även att arbeta med filer kan tyckas komplicerat, 172 00:09:51,410 --> 00:09:54,530 utnyttja dem tillåter oss att göra något verkligen anmärkningsvärt. 173 00:09:54,530 --> 00:09:58,880 Vi kan ändra tillståndet i världen utanför vårt program, 174 00:09:58,880 --> 00:10:01,730 Vi kan skapa något som lever bortom livet i vårt program, 175 00:10:01,730 --> 00:10:07,190 eller vi kan även ändra något som skapades före vårt program började springa. 176 00:10:07,190 --> 00:10:11,210 Interagera med filer är en verkligt kraftfull del av programmering i C. 177 00:10:11,210 --> 00:10:15,300 och jag är spännande att se vad du ska skapa med den i koden för att komma. 178 00:10:15,300 --> 00:10:19,770 Mitt namn är Jason Hirschhorn. Detta är CS50. 179 00:10:19,770 --> 00:10:21,770 [CS50.TV] 180 00:10:21,770 --> 00:10:25,940 >> [Skratt] 181 00:10:25,940 --> 00:10:29,330 Okej. Man ta. Nu kör vi. 182 00:10:49,000 --> 00:10:52,140 När vi tänker på en fil - >> Åh, vänta. Ursäkta. 183 00:10:52,140 --> 00:10:56,800 [Skratt] Okej. 184 00:11:06,620 --> 00:11:09,970 Hej där. 185 00:11:13,670 --> 00:11:16,310 När vi tänker på en fil - 186 00:11:17,610 --> 00:11:20,710 När du tänker på en fil - Okej. Berätta när du är redo. 187 00:11:20,710 --> 00:11:22,520 Åh, bra. 188 00:11:22,520 --> 00:11:26,180 Även läsa från en teleprompter kan tyckas - nej. Min dåliga.