[Powered by Google Translate] [File I / O]
[Jason Hirschhorn, Πανεπιστήμιο Χάρβαρντ]
[Αυτό είναι CS50, CS50.TV]
Όταν σκεφτόμαστε ένα αρχείο, τι έρχεται στο μυαλό είναι ένα έγγραφο του Microsoft Word,
μια εικόνα JPEG, MP3 ή ένα τραγούδι,
και εμείς αλληλεπιδρούν με κάθε ένα από αυτούς τους τύπους των αρχείων με διαφορετικούς τρόπους.
Για παράδειγμα, σε ένα έγγραφο του Word προσθέσουμε κείμενο
ενώ με μια εικόνα JPEG που μπορεί να προκύψουν από τις άκρες ή να διορθώσετε τα χρώματα.
Ωστόσο, κάτω από την κουκούλα όλα τα αρχεία στον υπολογιστή μας δεν είναι τίποτα περισσότερο
από μια μακρά σειρά από μηδενικά και μονάδες.
Είναι μέχρι την συγκεκριμένη εφαρμογή που αλληλεπιδρά με το αρχείο
να αποφασίσουν πώς θα επεξεργαστεί αυτή τη μακρά ακολουθία και να το παρουσιάσει στο χρήστη.
Από τη μία πλευρά, ένα έγγραφο μπορεί να φανεί σε ένα μόνο byte,
ή 8 μηδενικά και μονάδες, και να εμφανίσει ένα ASCII χαρακτήρα στην οθόνη.
Από την άλλη μεριά, μια εικόνα bitmap μπορεί να κοιτάξει 3 bytes,
ή 24 μηδενικά και μονάδες,
και να τους ερμηνεύουν ως 3 δεκαεξαδικούς αριθμούς
που αντιπροσωπεύουν τις τιμές για το κόκκινο, το πράσινο και το μπλε
σε ένα εικονοστοιχείο μιας εικόνας.
Ό, τι μπορεί να μοιάζει στην οθόνη σας, στον πυρήνα τους,
τα αρχεία δεν είναι τίποτα περισσότερο από μια ακολουθία από μηδενικά και μονάδες.
Έτσι, ας βουτιά σε και να δούμε πώς θα χειριστεί αυτά τα πραγματικά μηδενικά και μονάδες
όταν πρόκειται για γραφή και την ανάγνωση από ένα αρχείο.
>> Θα ξεκινήσω με το σπάσιμο προς τα κάτω σε μια απλή διαδικασία 3-μέρος.
Στη συνέχεια, θα βουτήξει σε δύο παραδείγματα κώδικα που αποδεικνύουν αυτά τα τρία μέρη.
Τέλος, θα επανεξετάσει τη διαδικασία και μερικά από τα πιο σημαντικά στοιχεία του.
Όπως και με οποιοδήποτε αρχείο που βρίσκεται στην επιφάνεια εργασίας σας,
το πρώτο πράγμα που πρέπει να κάνετε είναι να το ανοίξετε.
Στην Γ κάνουμε αυτό, δηλώνοντας ένα δείκτη σε μια προκαθορισμένη struct
που αντιπροσωπεύει ένα αρχείο στο δίσκο.
Σε αυτή την κλήση της συνάρτησης, μπορούμε επίσης να αποφασίσουμε αν θέλουμε να γράψετε ή να διαβάσετε από το αρχείο.
Στη συνέχεια, κάνουμε την πραγματική ανάγνωση και τη γραφή.
Υπάρχουν μια σειρά από εξειδικευμένες λειτουργίες που μπορούμε να χρησιμοποιήσουμε σε αυτό το μέρος,
και σχεδόν όλοι τους αρχίζουν με το γράμμα F, το οποίο ξεχωρίζει για το αρχείο.
Τελευταία, παρόμοια με τα μικρά κόκκινα Χ στην επάνω γωνία του τα αρχεία ανοίγουν στον υπολογιστή σας,
κλείνουμε το αρχείο με την τελική κλήση της συνάρτησης.
Τώρα που έχουμε μια γενική ιδέα για το τι θα πάμε να κάνουμε,
ας βουτιά στον κώδικα.
>> Σε αυτόν τον κατάλογο, έχουμε δύο αρχεία και C αντίστοιχα εκτελέσιμα αρχεία τους.
Το πρόγραμμα γραφομηχανή παίρνει ένα όρισμα της γραμμής εντολών,
το όνομα του εγγράφου που θέλουμε να δημιουργήσουμε.
Σε αυτή την περίπτωση, θα καλέσουμε το doc.txt.
Ας τρέξει το πρόγραμμα και εισάγετε ένα ζευγάρι των γραμμών.
Γεια σας. Το όνομά μου είναι Jason.
Τέλος, θα πληκτρολογήσετε "σταματήσουν το κάπνισμα."
Αν τώρα λίστα όλα τα αρχεία σε αυτόν τον κατάλογο,
βλέπουμε ότι ένα νέο έγγραφο που ονομάζεται doc.txt υπάρχει.
Αυτό είναι το αρχείο αυτό το πρόγραμμα μόλις δημιουργήσατε.
Και φυσικά, είναι πολύ τίποτα περισσότερο από μια μακρά ακολουθία από μηδενικά και μονάδες.
Εάν ανοίξετε αυτό το νέο αρχείο,
βλέπουμε τις 3 γραμμές κώδικα μπήκαμε στο πρόγραμμά μας -
Γεια σας. Μαΐου όνομα είναι Jason.
Αλλά τι πραγματικά συμβαίνει όταν typewriter.c τρέχει;
Η πρώτη γραμμή του ενδιαφέροντος για μας είναι η γραμμή 24.
Σε αυτή τη γραμμή, έχουμε δηλώσει δείκτη του αρχείου μας.
Η συνάρτηση που επιστρέφει το δείκτη, fopen, παίρνει δύο επιχειρήματα.
Το πρώτο είναι το όνομα του αρχείου, συμπεριλαμβανομένης της επέκτασης αρχείου ανάλογα με την περίπτωση.
Θυμηθείτε ότι μια επέκταση αρχείου δεν επηρεάζει το αρχείο στο χαμηλότερο επίπεδό της.
Είμαστε πάντα ασχολούνται με μια μεγάλη σειρά από μηδενικά και μονάδες.
Αλλά αυτό δεν επηρεάζει το πώς ερμηνεύονται τα αρχεία και οι εφαρμογές που χρησιμοποιούνται τι να τα ανοίξετε.
Το δεύτερο επιχείρημα για fopen είναι ένα μεμονωμένο γράμμα
που ξεχωρίζει για το τι σκοπεύουμε να κάνουμε εμείς μετά το άνοιγμα του αρχείου.
Υπάρχουν τρεις επιλογές για αυτό το επιχείρημα - W, R, και Α.
Έχουμε επιλέξει w σε αυτή την περίπτωση, γιατί θέλουμε να γράψουμε στο αρχείο.
R, όπως μπορείτε να μαντέψετε, είναι για την ανάγνωση του αρχείου.
Και μια είναι για προσαρτώντας στο αρχείο.
Ενώ και οι δύο νν και ένας μπορεί να χρησιμοποιηθεί για γραφή σε αρχεία,
νν θα αρχίσει να γράφει από την αρχή του αρχείου
και ενδεχομένως να αντικαταστήσετε όλα τα δεδομένα που έχουν ήδη αποθηκευτεί.
Από προεπιλογή, το αρχείο θα ανοίξει, εάν δεν υπάρχει ήδη,
δημιουργείται στην παρούσα κατάλογο εργασίας μας.
Ωστόσο, αν θέλουμε να έχουν πρόσβαση ή να δημιουργήσετε ένα αρχείο σε διαφορετική θέση,
κατά το πρώτο επιχείρημα της fopen,
μπορούμε να καθορίσετε μια διαδρομή αρχείου εκτός από το όνομα του αρχείου.
Ενώ το πρώτο μέρος αυτής της διαδικασίας είναι μόνο μία γραμμή κώδικα μακρύ,
είναι πάντα καλή πρακτική να περιλαμβάνουν ένα άλλο σύνολο των γραμμών
ότι το check για να βεβαιωθείτε ότι το αρχείο με επιτυχία ανοίξει ή δημιουργήσει.
Αν fopen επιστρέφει null, δεν θα θέλαμε να προχωρήσουμε με το πρόγραμμά μας,
και αυτό μπορεί να συμβεί εάν το λειτουργικό σύστημα είναι έξω από τη μνήμη
ή αν προσπαθείτε να ανοίξετε ένα αρχείο σε έναν κατάλογο για τον οποίο δεν είχαμε τα κατάλληλα δικαιώματα.
>> Το δεύτερο μέρος της διαδικασίας λαμβάνει χώρα στο βρόχο, ενώ γραφομηχανή του.
Χρησιμοποιούμε ένα CS50 λειτουργία της βιβλιοθήκης για να πάρετε είσοδο από το χρήστη,
και με την παραδοχή ότι δεν θέλουν να σταματήσουν το πρόγραμμα,
χρησιμοποιούμε τα fputs λειτουργία για να λάβει το string και να το γράψετε στο αρχείο.
fputs είναι μόνο μία από τις πολλές λειτουργίες που θα μπορούσαμε να χρησιμοποιήσουμε για να γράψουμε στο αρχείο.
Άλλοι περιλαμβάνουν fwrite, fputc, ακόμη και fprintf.
Ανεξάρτητα από την συγκεκριμένη λειτουργία καταλήγουμε χρησιμοποιώντας, όμως,
όλα αυτά πρέπει να γνωρίζουν, μέσω των επιχειρημάτων τους,
τουλάχιστον δύο πράγματα -
τι πρέπει να γραφτεί και όπου χρειάζεται να γραφτεί σε.
Στην περίπτωσή μας, η είσοδος είναι η συμβολοσειρά που πρέπει να γραφτεί
και fp είναι ο δείκτης που μας κατευθύνει εκεί που γράφουμε.
Σε αυτό το πρόγραμμα, το δεύτερο μέρος της διαδικασίας είναι μάλλον απλή.
Παίρνουμε απλά μια σειρά από τον χρήστη
και προσθέτοντας απευθείας στο αρχείο μας με λίγο έως καθόλου επικύρωση των εισροών ή οι έλεγχοι ασφαλείας.
Συχνά, όμως, το δεύτερο μέρος θα αναλάβει το μεγαλύτερο μέρος του κώδικα σας.
Τέλος, το τρίτο μέρος είναι στη γραμμή 58, όπου κλείνουμε το αρχείο.
Εδώ καλούμε fclose και να περάσει το αρχικό δείκτη του αρχείου μας.
Στην επόμενη γραμμή, θα επιστρέψουμε το μηδέν, σηματοδοτώντας το τέλος του προγράμματός μας.
Και, ναι, το τρίτο μέρος είναι τόσο απλό.
>> Ας προχωρήσουμε στην ανάγνωση από αρχεία.
Επιστροφή στον κατάλογο μας έχουμε ένα αρχείο που ονομάζεται printer.c.
Ας το τρέξετε με το αρχείο που μόλις δημιουργήσατε -
doc.txt.
Το πρόγραμμα αυτό, όπως υποδηλώνει το όνομα, απλά θα εκτυπώσει από το περιεχόμενο του αρχείου για να το περάσει.
Και εκεί έχουμε.
Οι γραμμές του κώδικα που είχε πληκτρολογήσει νωρίτερα και να αποθηκευτεί σε doc.txt.
Γεια σας. Το όνομά μου είναι Jason.
Αν βουτήξει printer.c,
βλέπουμε ότι ένα μεγάλο μέρος του κώδικα μοιάζει με αυτό που μόλις μπήκε μέσα στο typewriter.c.
Πράγματι γραμμή 22, όπου ανοίξαμε το αρχείο,
και η γραμμή 39, όπου κλείσαμε το αρχείο,
είναι και οι δύο σχεδόν πανομοιότυπα με typewriter.c, εκτός fopen δεύτερο επιχείρημα.
Αυτή τη φορά είμαστε ανάγνωση από ένα αρχείο,
έτσι έχουμε επιλέξει, αντί του r w.
Έτσι, ας επικεντρωθεί στο δεύτερο μέρος της διαδικασίας.
Στη γραμμή 35, ως δεύτερη προϋπόθεση σε 4 βρόχο μας,
κάνουμε μια κλήση με fgets,
η λειτουργία σύντροφος για fputs από πριν.
Αυτή τη φορά έχουμε τρία επιχειρήματα.
Ο πρώτος είναι ο δείκτης προς τη συστοιχία των χαρακτήρων, όπου η συμβολοσειρά θα αποθηκευτεί.
Ο δεύτερος είναι ο μέγιστος αριθμός των χαρακτήρων που θα διαβάσετε.
Και το τρίτο είναι ο δείκτης στο αρχείο με το οποίο δουλεύουμε.
Θα παρατηρήσετε ότι ο βρόχος for τελειώνει όταν fgets επιστρέφει null.
Υπάρχουν δύο λόγος για τον οποίο αυτό μπορεί να συμβεί.
Κατ 'αρχάς, ένα λάθος μπορεί να έχει συμβεί.
Δεύτερον, και πιο πιθανό, το τέλος του αρχείου επιτεύχθηκε και πλέον χαρακτήρες είχαν διαβάσει.
Σε περίπτωση που αναρωτιέστε, δύο λειτουργίες υπάρχουν ότι θα μας επιτρέψουν να πει
οποία λόγος είναι η αιτία για αυτό το συγκεκριμένο δείκτη null.
Και, όπως ήταν αναμενόμενο, δεδομένου ότι έχουν να κάνουν με την εργασία με τα αρχεία,
τόσο η λειτουργία π.χ. η ferror και η έναρξη λειτουργίας feof με το γράμμα f.
>> Τέλος, πριν ολοκληρώσουμε, μια γρήγορη σημείωση σχετικά με το τέλος της λειτουργίας του αρχείου,
το οποίο, όπως μόλις ανέφερα, είναι γραμμένο ως feof.
Συχνά θα βρείτε τον εαυτό σας με τη χρήση, ενώ και για βρόχους να διαβάσετε σταδιακά το δρόμο σας μέσα από τα αρχεία.
Έτσι, θα χρειαστείτε έναν τρόπο για να σταματήσει αυτές τις θηλιές αφού φτάσετε στο τέλος αυτών των αρχείων.
Κλήση για feof δείκτη αρχείο σας και τον έλεγχο για να δούμε αν είναι αλήθεια
θα κάνουν ακριβώς αυτό.
Έτσι, ένα βρόχο, ενώ με τον όρο (! Feof (fp)) μπορεί να φαίνεται σαν μια τέλεια κατάλληλη λύση.
Ωστόσο, λένε ότι έχουμε μία γραμμή αριστερά στο αρχείο κειμένου μας.
Θα τεθεί βρόχο, ενώ μας και όλα θα πάνε όπως είχε προγραμματιστεί.
Στο επόμενο γύρο μέσω του προγράμματος μας θα ελέγξει για να δει εάν feof του fp είναι αλήθεια,
αλλά - και αυτό είναι το κρίσιμο σημείο για να καταλάβουμε εδώ -
δεν θα ισχύει ακόμα.
Αυτό συμβαίνει γιατί ο σκοπός του δεν είναι feof να ελέγξετε
αν η επόμενη κλήση σε μια λειτουργία ανάγνωσης θα χτυπήσει το τέλος του αρχείου,
αλλά μάλλον για να ελέγξετε αν ή όχι το τέλος του αρχείου έχει ήδη επιτευχθεί.
Στην περίπτωση του παραδείγματος αυτού,
διαβάζοντας την τελευταία γραμμή του αρχείου μας πηγαίνει τέλεια ομαλά,
αλλά το πρόγραμμα δεν γνωρίζει ακόμη ότι έχουμε χτυπήσει το τέλος του αρχείου μας.
Δεν είναι μέχρι να κάνει μια επιπλέον ανάγνωση ότι μετρητές το τέλος του αρχείου.
Ετσι, μια σωστή προϋπόθεση θα είναι η ακόλουθη:
fgets και τρία επιχειρήματα του - παραγωγή, το μέγεθος της παραγωγής, και fp -
και όλα αυτά δεν είναι ίσο με το μηδέν.
Αυτή είναι η προσέγγιση που κάναμε στο printer.c,
και στην περίπτωση αυτή, μετά από τις εξόδους βρόχου,
μπορείτε να καλέσετε ή feof π.χ. η ferror να ενημερώσει το χρήστη με τη συγκεκριμένη αιτιολογία για την έξοδο από αυτή βρόχο.
>> Γράφοντας και την ανάγνωση από ένα αρχείο είναι, στο πιο βασικό του,
ένα απλό 3-μέρος της διαδικασίας.
Πρώτον, το άνοιγμα του αρχείου.
Δεύτερον, βάζουμε κάποια πράγματα στο αρχείο μας ή να πάρετε κάποια πράγματα έξω από αυτό.
Τρίτον, κλείστε το αρχείο.
Η πρώτη και η τελευταία μέρη είναι εύκολο.
Το μεσαίο τμήμα είναι όπου η ουσία βρίσκεται δύσκολη.
Και όμως κάτω από το καπό είμαστε πάντα ασχολούνται με μια μεγάλη σειρά από μηδενικά και μονάδες,
βοηθάει όταν κωδικοποίησης για να προσθέσετε ένα στρώμα αφαίρεσης
που μετατρέπει την ακολουθία σε κάτι που μοιάζει περισσότερο με αυτό που έχουμε συνηθίσει να βλέπουμε.
Για παράδειγμα, εάν εργάζεστε με μια 24-bit αρχείο bitmap,
εμείς μάλλον θα πρέπει να διαβάζει ή να γράφει τρία bytes κάθε φορά.
Σε αυτή την περίπτωση, θα ήταν λογικό να καθορίζουν κατάλληλα και το όνομα
ένα struct που είναι 3 bytes μεγάλο.
>> Αν εργάζεστε με αρχεία μπορεί να φαίνεται περίπλοκη,
χρησιμοποιώντας τους μας επιτρέπει να κάνουμε κάτι πραγματικά αξιόλογο.
Μπορούμε να αλλάξουμε την κατάσταση του κόσμου έξω από το πρόγραμμά μας,
μπορούμε να δημιουργήσουμε κάτι που ζει πέρα ​​από τη διάρκεια ζωής του προγράμματος μας,
ή μπορούμε να αλλάξουμε κάτι ακόμη που δημιουργήθηκε πριν από το πρόγραμμά μας άρχισε να τρέχει.
Αλληλεπίδραση με τα αρχεία είναι ένα πραγματικά ισχυρό μέρος του προγραμματισμού σε C.
και είμαι ενθουσιασμένος για να δείτε τι πρόκειται να δημιουργηθεί με αυτό τον κωδικό για να έρθει.
Το όνομά μου είναι Jason Hirschhorn. Αυτό είναι CS50.
[CS50.TV]
>> [Γέλια]
Εντάξει. Ένα λάβει. Εδώ πάμε.
Όταν σκεφτόμαστε ένα αρχείο - >> Αχ, περιμένετε. Λυπάμαι.
[Γέλια] Εντάξει.
Hey εκεί.
Όταν σκεφτόμαστε ένα αρχείο -
Όταν σκέφτεστε από ένα αρχείο - Εντάξει. Πείτε μου, όταν είστε έτοιμοι.
Ω, μεγάλη.
Αν και την ανάγνωση από μια teleprompter μπορεί να φαίνεται - όχι. Κακή μου.