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, Universitatea Harvard] 3 00:00:04,000 --> 00:00:07,000 [Acest lucru este CS50, CS50.TV] 4 00:00:07,000 --> 00:00:11,000 Când ne gândim la un fișier, ceea ce vine în minte este un document Microsoft Word, 5 00:00:11,000 --> 00:00:14,000 o imagine JPEG, sau o melodie MP3, 6 00:00:14,000 --> 00:00:17,000 și am interacționa cu fiecare dintre aceste tipuri de fișiere în moduri diferite. 7 00:00:17,000 --> 00:00:20,000 De exemplu, într-un document Word se adauga text 8 00:00:20,000 --> 00:00:24,000 în timp ce, cu o imagine JPEG am putea decupa margini sau retușa culorile. 9 00:00:24,000 --> 00:00:28,000 Cu toate acestea, sub capota toate fișierele din computerul nostru nu sunt nimic mai mult 10 00:00:28,000 --> 00:00:31,000 decât o secvență lungă de zero-uri și unu. 11 00:00:31,000 --> 00:00:33,000 Este, până la aplicații specifice, care interacționează cu dosarul 12 00:00:33,000 --> 00:00:38,000 să decidă cum să proceseze această secvență lungă și să îl prezinte utilizatorului. 13 00:00:38,000 --> 00:00:41,000 Pe de o parte, un document poate te uiti la un singur octet, 14 00:00:41,000 --> 00:00:45,000 sau 8 zerouri și cele, și afișează un caracter ASCII pe ecran. 15 00:00:45,000 --> 00:00:48,000 Pe de altă parte, o imagine bitmap poate arata la 3 octeți, 16 00:00:48,000 --> 00:00:50,000 sau 24 de zerouri și cele, 17 00:00:50,000 --> 00:00:53,000 și le interpreteze ca 3 numere hexazecimale 18 00:00:53,000 --> 00:00:56,000 care reprezintă valorile pentru roșu, verde și albastru 19 00:00:56,000 --> 00:00:58,000 într-un pixel dintr-o imagine. 20 00:00:58,000 --> 00:01:01,000 Indiferent care sunt acestea arata ca pe ecran, de la lor de bază, 21 00:01:01,000 --> 00:01:05,000 Fișierele nu sunt nimic mai mult decât o secvență de zero-uri și cele. 22 00:01:05,000 --> 00:01:08,000 Deci, haideți să se arunca cu capul în și uita-te la modul în care ne manipuleze, de fapt aceste zero și unu 23 00:01:08,000 --> 00:01:12,000 atunci când vine vorba de scris și de citit dintr-un fișier. 24 00:01:12,000 --> 00:01:15,000 >> Voi începe prin rupere-l în jos într-un simplu proces de 3-o parte. 25 00:01:15,000 --> 00:01:19,000 În continuare, voi arunca cu capul în două exemple de cod care să demonstreze aceste trei părți. 26 00:01:19,000 --> 00:01:23,000 În cele din urmă, voi revizui procesul, iar unele dintre detaliile sale cele mai importante. 27 00:01:23,000 --> 00:01:25,000 Ca în orice fișier care se află pe desktop, 28 00:01:25,000 --> 00:01:28,000 primul lucru de făcut este să-l deschidă. 29 00:01:28,000 --> 00:01:31,000 În C vom face acest lucru prin a declara un pointer la o structura predefinit 30 00:01:31,000 --> 00:01:33,000 care reprezintă un fișier de pe disc. 31 00:01:33,000 --> 00:01:38,460 În acest apel de funcție, am, de asemenea, să decidem dacă vrem să scrie sau citi din fișierul. 32 00:01:38,460 --> 00:01:41,660 În continuare, vom face citirea real și scris. 33 00:01:41,660 --> 00:01:44,800 Există o serie de funcții de specialitate putem folosi în această parte, 34 00:01:44,800 --> 00:01:48,790 și aproape toți dintre ei incep cu litera F, care vine de la dosar. 35 00:01:48,790 --> 00:01:53,560 În sfârșit, asemănător cu X mici roșii în colțul de sus al fisierelor deschide pe computer, 36 00:01:53,560 --> 00:01:56,680 am închide fișierul cu un apel de funcție finală. 37 00:01:56,680 --> 00:01:59,540 Acum, că avem o idee generală despre ceea ce vom face, 38 00:01:59,540 --> 00:02:02,000 Haideti sa patrundem in cod. 39 00:02:02,000 --> 00:02:06,100 >> În acest director, avem două fișiere C și dosarele lor corespunzătoare executabile. 40 00:02:06,100 --> 00:02:09,710 Programul de mașină de scris are un argument de linie de comandă, 41 00:02:09,710 --> 00:02:12,060 denumirea documentului dorim să creăm. 42 00:02:12,060 --> 00:02:16,160 În acest caz, vom numi doc.txt. 43 00:02:16,160 --> 00:02:19,080 Să rula programul și introduceți un cuplu de linii. 44 00:02:19,080 --> 00:02:23,660 Hi. Numele meu este Jason. 45 00:02:23,660 --> 00:02:26,710 În cele din urmă, vom tastați "demisia". 46 00:02:26,710 --> 00:02:29,720 Dacă am lista acum toate fișierele din acest director, 47 00:02:29,720 --> 00:02:33,770 vom vedea că un nou document numit Exista doc.txt. 48 00:02:34,190 --> 00:02:36,110 Asta e fișierul acest program tocmai creat. 49 00:02:36,110 --> 00:02:40,520 Și, bineînțeles, prea este nimic mai mult decât o secvență lungă de zero-uri și unu. 50 00:02:41,100 --> 00:02:43,260 Dacă vom deschide acest fișier nou, 51 00:02:43,260 --> 00:02:45,870 vom vedea cele 3 linii de cod am intrat în programul nostru - 52 00:02:46,060 --> 00:02:49,060 Hi. Numele mai este Jason. 53 00:02:49,580 --> 00:02:52,090 Dar ce se întâmplă de fapt atunci când typewriter.c ruleaza? 54 00:02:52,810 --> 00:02:55,520 Prima linie de interes pentru noi este linia 24. 55 00:02:55,560 --> 00:02:58,490 În această linie, ne declarăm indicatorul nostru fișier. 56 00:02:59,080 --> 00:03:03,140 Funcția care returnează acest pointer, fopen, ia două argumente. 57 00:03:03,140 --> 00:03:07,440 Primul este numele fișierului, inclusiv extensia de fișier, dacă este cazul. 58 00:03:07,440 --> 00:03:10,980 Amintiti-va ca o extensie de fișier nu influențează dosarului la nivelul cel mai scăzut. 59 00:03:10,980 --> 00:03:14,640 Noi suntem întotdeauna de-a face cu o secvență lungă de zero-uri și unu. 60 00:03:14,640 --> 00:03:19,630 Dar ea nu influențează modul în care fișierele sunt interpretate și aplicațiile care sunt utilizate pentru a le deschide. 61 00:03:19,630 --> 00:03:22,290 Al doilea argument pentru a fopen este o singură literă 62 00:03:22,290 --> 00:03:25,300 care stă pentru ceea ce avem de gând să facem după ce am deschis fișierul. 63 00:03:25,300 --> 00:03:30,630 Există trei opțiuni pentru acest argument - W, R, și A. 64 00:03:30,630 --> 00:03:34,900 Am ales g, în acest caz, pentru că vrem să scrie la dosar. 65 00:03:34,900 --> 00:03:38,820 R, după cum puteți ghici, probabil, este pentru citirea la dosar. 66 00:03:38,820 --> 00:03:41,760 Și o este pentru adăugarea la dosar. 67 00:03:41,760 --> 00:03:44,960 În timp ce ambele w și o pot fi folosite pentru scrierea de la fișiere, 68 00:03:44,960 --> 00:03:47,460 w va începe scrierea de la începutul fișierului 69 00:03:47,460 --> 00:03:50,810 si suprascrie potențial orice date care au fost anterior stocate. 70 00:03:50,810 --> 00:03:54,070 În mod implicit, fișierul ne deschide, în cazul în care nu există deja, 71 00:03:54,070 --> 00:03:57,180 este creat în directorul nostru de muncă actual. 72 00:03:57,180 --> 00:04:00,540 Cu toate acestea, în cazul în care dorim să acceseze sau să creați un fișier într-o locație diferită, 73 00:04:00,540 --> 00:04:02,650 în primul argument al fopen, 74 00:04:02,650 --> 00:04:05,840 am putea specifica o cale de fișier în plus față de numele fișierului. 75 00:04:05,840 --> 00:04:09,490 În timp ce prima parte a acestui proces este doar o linie de cod lung, 76 00:04:09,490 --> 00:04:12,350 este întotdeauna de bună practică pentru a include un alt set de linii 77 00:04:12,350 --> 00:04:15,930 care să se asigure că dosarul a fost deschis cu succes sau create. 78 00:04:15,930 --> 00:04:20,300 Dacă fopen returnează null, noi nu ar vrea să merge înainte cu programul nostru, 79 00:04:20,300 --> 00:04:23,270 iar acest lucru se poate întâmpla în cazul în care sistemul de operare este în afara de memorie 80 00:04:23,270 --> 00:04:27,940 sau în cazul în care vom încerca să deschideți un fișier într-un director pentru care noi nu avem permisiunile corespunzătoare. 81 00:04:27,940 --> 00:04:31,780 >> Partea a doua a procesului de are loc în buclă în timp ce mașina de scris a lui. 82 00:04:31,780 --> 00:04:35,000 Noi folosim o funcție de bibliotecă CS50 pentru a obține de intrare de la utilizator, 83 00:04:35,000 --> 00:04:37,190 și presupunând că nu doresc să renunțe programul, 84 00:04:37,190 --> 00:04:41,940 am folosit funcția fputs să ia șir și scrie-l la dosar. 85 00:04:41,940 --> 00:04:46,700 fputs este doar unul dintre multe funcții le-ar putea folosi pentru a scrie la dosar. 86 00:04:46,700 --> 00:04:51,920 Altele includ fwrite, fputc, și chiar fprintf. 87 00:04:51,920 --> 00:04:54,840 Indiferent de anumite funcții vom ajunge folosind, însă, 88 00:04:54,840 --> 00:04:57,480 toate acestea trebuie să știe, prin argumentele lor, 89 00:04:57,480 --> 00:04:59,670 cel puțin două lucruri - 90 00:04:59,670 --> 00:05:03,140 ceea ce trebuie să fie scrisă și în cazul în care acesta trebuie să fie scris. 91 00:05:03,140 --> 00:05:07,240 În cazul nostru, de intrare este șirul care trebuie să fie scrise 92 00:05:07,240 --> 00:05:11,290 și FP este indicatorul care ne îndrumă acolo unde suntem scris. 93 00:05:11,290 --> 00:05:15,330 În acest program, partea a doua a procesului este destul de simplu. 94 00:05:15,330 --> 00:05:17,360 Luăm doar un șir de utilizator 95 00:05:17,360 --> 00:05:22,120 și adăugarea direct la dosarul nostru cu mic-la-nici o validare de intrare sau de controalele de securitate. 96 00:05:22,120 --> 00:05:26,160 De multe ori, cu toate acestea, partea a doua va dura până cea mai mare parte a codului. 97 00:05:26,160 --> 00:05:30,580 În cele din urmă, partea a treia, este pe linia 58, în cazul în care vom închide fișierul. 98 00:05:30,580 --> 00:05:34,860 Aici ne numim fclose și trece-l pointerul nostru fișierul original. 99 00:05:34,860 --> 00:05:39,500 În linia următoare, vom reveni la zero, de semnalizare sfârșitul programului nostru. 100 00:05:39,500 --> 00:05:42,630 Și, da, partea a treia este la fel de simplu ca asta. 101 00:05:42,630 --> 00:05:45,260 >> Să trecem la citirea din fișiere. 102 00:05:45,260 --> 00:05:48,220 Înapoi în directorul nostru, avem un fișier numit printer.c. 103 00:05:48,220 --> 00:05:50,910 Să-l rulați cu fișierul care tocmai am creat - 104 00:05:50,910 --> 00:05:53,350 doc.txt. 105 00:05:53,350 --> 00:05:58,150 Acest program, după cum sugerează și numele, va imprima pur și simplu conținutul fișierului a trecut să-l. 106 00:05:58,150 --> 00:06:00,230 Și acolo îl avem. 107 00:06:00,230 --> 00:06:03,780 Liniile de cod am tastat mai devreme și salvate în doc.txt. 108 00:06:03,780 --> 00:06:06,980 Hi. Numele meu este Jason. 109 00:06:06,980 --> 00:06:09,120 Dacă am arunca cu capul în printer.c, 110 00:06:09,120 --> 00:06:13,570 vom vedea că o mulțime de cod arata similar cu ceea ce ne-am plimbat prin în typewriter.c. 111 00:06:13,570 --> 00:06:16,720 Într-adevăr linia 22, în cazul în care am deschis fișierul, 112 00:06:16,720 --> 00:06:19,220 și linia 39, în cazul în care am închis dosarul, 113 00:06:19,220 --> 00:06:23,890 sunt ambele aproape identice cu typewriter.c, cu excepția argument fopen secunde. 114 00:06:23,890 --> 00:06:26,510 De data aceasta suntem citirea dintr-un fișier, 115 00:06:26,510 --> 00:06:29,040 de aceea am ales r în loc de w. 116 00:06:29,040 --> 00:06:31,950 Astfel, să ne concentrăm asupra a doua parte a procesului. 117 00:06:31,950 --> 00:06:36,060 În linia 35, astfel cum a doua condiție nostru de 4 buclă, 118 00:06:36,060 --> 00:06:38,590 facem un apel la fgets, 119 00:06:38,590 --> 00:06:42,190 funcția de însoțitor pentru fputs de dinainte. 120 00:06:42,190 --> 00:06:44,660 De data aceasta avem trei argumente. 121 00:06:44,660 --> 00:06:48,810 Primul este indicatorul la matrice de caractere în cazul în care șirul vor fi stocate. 122 00:06:48,810 --> 00:06:52,670 Al doilea este numărul maxim de caractere care urmează să fie citite. 123 00:06:52,670 --> 00:06:56,010 Iar al treilea este indicatorul la fișierul cu care lucram. 124 00:06:56,010 --> 00:07:00,780 Veți observa că pentru bucla se termină atunci când fgets returnează null. 125 00:07:00,780 --> 00:07:02,940 Există două motive care acest lucru ar putea să se fi întâmplat. 126 00:07:02,940 --> 00:07:05,380 În primul rând, o eroare poate au avut loc. 127 00:07:05,380 --> 00:07:10,740 În al doilea rând, și mai probabil, la sfârșitul dosarul a fost atins și personajele nu mai au fost citite. 128 00:07:10,740 --> 00:07:14,040 În caz că vă întrebați, nu există două funcții, care ne permit să-i spun 129 00:07:14,040 --> 00:07:17,160 care motiv este cauza pentru acest pointer nul special. 130 00:07:17,160 --> 00:07:21,090 Și, nu în mod surprinzător, deoarece acestea au de a face cu lucrul cu fișiere, 131 00:07:21,090 --> 00:07:26,940 atât funcția de ferror și începutul funcția feof cu litera F. 132 00:07:26,940 --> 00:07:32,130 >> În cele din urmă, înainte de a ne încheia, o scurtă notă despre sfârșitul funcției fișier, 133 00:07:32,130 --> 00:07:36,690 care, după cum am menționat, este scris ca feof. 134 00:07:36,690 --> 00:07:41,550 De multe ori te vei găsi în timp ce utilizați și pentru bucle pentru a citi progresiv drum prin fișiere. 135 00:07:41,550 --> 00:07:45,790 Astfel, veți avea nevoie de o modalitate de a pune capăt acestor bucle după ce ajunge la sfârșitul acestor fișiere. 136 00:07:45,790 --> 00:07:50,510 Apelarea feof pe indicatorul fișierul și verificare pentru a vedea dacă e adevărat 137 00:07:50,510 --> 00:07:52,310 ar face doar asta. 138 00:07:52,310 --> 00:07:59,820 Astfel, o buclă în timp ce, cu conditia (feof (fp)!) S-ar putea părea o soluție perfect adecvată. 139 00:07:59,820 --> 00:08:03,770 Cu toate acestea, spune ca avem o linie lăsat în fișier text noastră. 140 00:08:03,770 --> 00:08:07,130 Vom intra în buclă în timp ce noastre si totul va merge conform planului. 141 00:08:07,130 --> 00:08:12,750 La următoarea rundă, prin, programul nostru va verifica pentru a vedea dacă feof al FP este adevărat, 142 00:08:12,750 --> 00:08:15,430 dar - și acest lucru este punctul crucial să înțelegem aici - 143 00:08:15,430 --> 00:08:17,770 acesta nu va fi adevărat doar încă. 144 00:08:17,770 --> 00:08:21,110 Asta pentru că scopul feof nu este de a verifica 145 00:08:21,110 --> 00:08:24,400 în cazul în următorul apel la o funcție citi va lovi sfârșitul fișierului, 146 00:08:24,400 --> 00:08:28,190 ci mai degrabă pentru a verifica dacă este sau nu la sfârșitul fișierului a fost deja atins. 147 00:08:28,190 --> 00:08:30,140 În cazul acestui exemplu, 148 00:08:30,140 --> 00:08:32,780 lectură ultima linie a fișierului de merge perfect fara probleme, 149 00:08:32,780 --> 00:08:36,210 dar programul nu știe încă faptul că ne-am lovit la sfârșitul fișierului nostru. 150 00:08:36,210 --> 00:08:40,549 Nu e până când se face o citire suplimentare pe care le contracarează sfârșitul fișierului. 151 00:08:40,549 --> 00:08:43,210 Astfel, o condiție corectă ar fi următoarele: 152 00:08:43,210 --> 00:08:49,330 fgets și cele trei argumente - ieșire, mărimea de ieșire, și FP - 153 00:08:49,330 --> 00:08:52,570 și toate acestea nu este egal cu zero. 154 00:08:52,570 --> 00:08:55,260 Aceasta este abordarea am luat în printer.c, 155 00:08:55,260 --> 00:08:57,890 și, în acest caz, după ce iese din bucla, 156 00:08:57,890 --> 00:09:04,290 ai putea apela feof sau ferror pentru a informa utilizatorul cu privire la motivarea specifică pentru ieșirea din această buclă. 157 00:09:04,290 --> 00:09:08,100 >> Scrierea și citirea la dintr-un fișier este, în cea mai de bază, 158 00:09:08,100 --> 00:09:10,150 un simplu proces de 3-o parte. 159 00:09:10,150 --> 00:09:12,530 În primul rând, am deschideți fișierul. 160 00:09:12,530 --> 00:09:16,740 În al doilea rând, am pus unele lucruri în fișierul nostru sau de a lua unele lucruri din ea. 161 00:09:16,740 --> 00:09:19,200 În al treilea rând, am închide fișierul. 162 00:09:19,200 --> 00:09:21,170 Piesele prima și ultima sunt ușor. 163 00:09:21,170 --> 00:09:23,920 Partea de mijloc este în cazul în care lucrurile se află complicat. 164 00:09:23,920 --> 00:09:27,760 Și, deși sub capota avem de-a face mereu cu o secvență lungă de zero-uri și unu, 165 00:09:27,760 --> 00:09:30,710 aceasta nu ajută atunci când de codificare pentru a adăuga un strat de abstractizare 166 00:09:30,710 --> 00:09:35,350 care transformă secvența în ceva care seamana foarte mult cu ceea ce suntem obișnuiți să vedem. 167 00:09:35,350 --> 00:09:39,570 De exemplu, dacă lucrăm cu un fișier de tip bitmap de 24 de biți, 168 00:09:39,570 --> 00:09:43,290 vom fi probabil la citirea sau scrierea trei octeți la un moment dat. 169 00:09:43,290 --> 00:09:46,450 În acest caz, aceasta ar avea sens să definească și să numească în mod corespunzător 170 00:09:46,450 --> 00:09:48,980 un struct care este de 3 octeți mare. 171 00:09:48,980 --> 00:09:51,410 >> Deși lucrul cu fișiere poate părea complicat, 172 00:09:51,410 --> 00:09:54,530 a le utiliza ne permite să facem ceva cu adevărat remarcabil. 173 00:09:54,530 --> 00:09:58,880 Putem schimba starea lumii din afara programului nostru, 174 00:09:58,880 --> 00:10:01,730 putem crea ceva care trăiește dincolo de viața al programului nostru, 175 00:10:01,730 --> 00:10:07,190 sau putem schimba ceva chiar și care a fost creat înainte de programul nostru a început să ruleze. 176 00:10:07,190 --> 00:10:11,210 Interacțiunea cu fișiere este o parte cu adevarat puternic de programare, în C. 177 00:10:11,210 --> 00:10:15,300 și eu sunt încântat să văd ce ai de gând să creeze cu ea în codul pentru a veni. 178 00:10:15,300 --> 00:10:19,770 Numele meu este Jason Hirschhorn. Acest lucru este CS50. 179 00:10:19,770 --> 00:10:21,770 [CS50.TV] 180 00:10:21,770 --> 00:10:25,940 >> [Râsete] 181 00:10:25,940 --> 00:10:29,330 Bine. Un iau. Aici vom merge. 182 00:10:49,000 --> 00:10:52,140 Când ne gândim la un fișier - >> Oh, stai. Scuze. 183 00:10:52,140 --> 00:10:56,800 [Râsete] Ok. 184 00:11:06,620 --> 00:11:09,970 Bună acolo. 185 00:11:13,670 --> 00:11:16,310 Când ne gândim la un fișier - 186 00:11:17,610 --> 00:11:20,710 Cand te gandesti la un fișier - Bine. Spune-mi când ești gata. 187 00:11:20,710 --> 00:11:22,520 Oh, minunat. 188 00:11:22,520 --> 00:11:26,180 Deși citirea de la un prompter poate parea - nr. Greșeala mea.