Τεχνικές αρχείων
Διομήδης Σπινέλλης
Τμήμα Διοικητικής Επιστήμης και Τεχνολογίας
Οικονομικό Πανεπιστήμιο Αθηνών
dds@aueb.gr
Βοηθητική μνήμη
- Η βοηθητική μνήμη διαφέρει από την κύρια ως προς:
- το κόστος ανά byte (μικρότερο),
- το χρόνο πρόσβασης (μεγαλύτερος) και
- τη χωρητικότητα (μεγαλύτερη).
- Βασικές τεχνολογίες βοηθητικής μνήμης είναι:
- οι μαγνητικές ταινίες,
- οι μαγνητικοί δίσκοι,
- οι οπτικοί δίσκοι (CD-ROM, CD-R, CD-RW, DVD),
- οι μαγνητο-οπτικοί δίσκοι.
- Ανάλογα με την τεχνολογία βοηθητικής μνήμης στα
δεδομένα των αρχείων μπορούμε να έχουμε
σειριακή προσπέλαση (serial access) (λ.χ. μαγνητική ταινία) ή
τυχαία προσπέλαση (random access) (λ.χ. μαγνητικός δίσκος).
- Τα δεδομένα σε δίσκους είναι στις περισσότερες περιπτώσεις
οργανωμένα σε
κυλίνδρους, (cylinders)
αυλάκια (tracks),
και
τομείς (sectors).
Εξαίρεση στην οργάνωση αυτή
αποτελούν οι δίσκοι CD-ROM όπου τα δεδομένα είναι οργανωμένα
σε σπείρα.
- Πρόσβαση στα στοιχεία ενός αρχείου γίνεται μέσω μιας ιεραρχίας
λογισμικού που μπορεί να περιλαμβάνει:
- το λογισμικό της εφαρμογής,
- το ενδιάμεσο λογισμικό (middleware),
- το λογισμικό της βάσης δεδομένων ή αντίστοιχες βιβλιοθήκες,
- το λειτουργικό σύστημα και συγκεκριμένα το σύστημα αρχείων,
- τον οδηγό συσκευής,
- το λογισμικό ελέγχου της συσκευής (firmware).
- Σημασία στην υλοποίηση του τρόπου χειρισμού των αρχείων έχει η ταχύτητα
των μονάδων βοηθητικής μνήμης.
Αυτή είναι της τάξης των ms σε αντιπαράθεση με την ταχύτητα
της κύριας μνήμης η οποία είναι της τάξης των δεκάδων ns.
Αρχεία
- Τα δεδομένα στη βοηθητική μνήμη
(π.χ. σκληρό δίσκο, CD-RW)
φυλάσσονται ομαδοποιημένα σε
αρχεία (files).
- Η οργάνωση των αρχείων εξαρτάται από την εφαρμογή που τα
δημιουργεί και τα διαβάζει.
Τα παρακάτω αποτελούν παραδείγματα περιεχομένου ενός αρχείου:
- Αδόμητο κείμενο
- Πηγαίος κώδικας (λ.χ. C, Java, συμβολική γλώσσα)
- Εκτελέσιμο πρόγραμμα
- Αρχείο βάσης δεδομένων
- Αρχείο δεδομένων εφαρμογής (λ.χ. Word, Excel)
- Αρχεία τα οποία περιέχουν ομοειδή στοιχεία οργανώνονται με βάση τις
εγγραφές.
- Κάθε εγγραφή περιέχει έναν αριθμό από πεδία τα οποία χαρακτηρίζονται
από το μήκος τους και τον τύπο των δεδομένων που περιέχουν.
Για λόγους ευκολίας αναφερόμαστε στα πεδία με βάση κάποιο όνομα ανάλογα με
τα δεδομένα που περιέχουν (π.χ. ΟΝΟΜΑ, ΥΠΟΛΟΙΠΟ).
- Η διάταξη των πεδίων στην εγγραφή καθώς και το είδος των πεδίων
ενός αρχείου καλείται γραμμογράφηση (layout) του αρχείου.
Επεξεργασία σειριακών αρχείων
- Εφαρμογές που επεξεργάζονται σειριακά αρχεία (λ.χ. αρχεία που
φυλάσσονται σε μαγνητικές ταινίες) είναι δομημένες με βάση διεργασίες
που διαβάζουν σειριακά ένα ή περισσότερα αρχεία και παράγουν,
σειριακά, νέα αρχεία.
- Ο όγκος των στοιχείων στις εφαρμογές αυτές φυλάσσεται στο
κύριο αρχείο (master file)
ενώ οι συναλλαγές κάθε ημέρας ή περιόδου φυλάσσονται στο
αρχείο συναλλαγών (transaction file)
- Στα αρχεία αυτά διακρίνουμε τις παρακάτω διεργασίες:
- Σύζευξη αρχείων (merge):
ένωση δύο σειριακών ταξινομημένων αρχείων σε τρίτο ταξινομημένο.
- Ταξινόμηση (sort): Ταξινόμηση των εγγραφών του
αρχείου με βάση κάποιο κλειδί της εγγραφής.
Η ταξινόμηση πραγματοποιείται συνήθως στην κύρια μνήμη.
Αν τα δεδομένα δε χωράνε στην κύρια μνήμη ταξινομείται το αρχείο
ανά τμήματα τα οποία στη συνέχεια ενώνονται με σύζευξη.
- Ενημέρωση (update):
ενημέρωση του ταξινομημένου κυρίου αρχείου με βάση το αρχείο συναλλαγών.
- Ερώτηση (query)
δημιουργία αρχείου που περιέχει τα δεδομένα που ικανοποιούν κάποιο κριτήριο.
- Αναφορά (report):
δημιουργία μιας διαμορφωμένης αναφοράς από τα στοιχεία του αρχείου.
Αρχεία τυχαίας προσπέλασης
- Τα αρχεία τυχαίας προσπέλασης είναι συνήθως οργανωμένα σε
πίνακες με βάση το σχεσιακό μοντέλο.
- Τα προγράμματα βάσεων δεδομένων επιτρέπουν την οργάνωση μη
προκαθορισμένων στοιχείων σε αρχεία τυχαίας προσπέλασης.
- Για γρήγορη πρόσβαση στα στοιχεία κάθε πίνακα χρησιμοποιούνται
βοηθητικές δομές αναζήτησης με δείκτες στους κυρίους πίνακες.
- Τέτοιες δομές μπορεί να είναι:
- ταξινομημένοι πίνακες για στοιχεία που δε μεταβάλλονται,
- πίνακες κατακερματισμού,
- δένδρα.
- Στα αρχεία αυτά υπάρχει συνήθως σύστημα το οποίο οργανώνει τη
διάθεση του ελεύθερου χώρου που προέρχεται από διαγραφές.
- Οι αλλαγές στο κύριο αρχείο γίνονται συνήθως άμεσα.
Παράλληλα ενημερώνεται και ένα αρχείο συναλλαγών το οποίο επιτρέπει
την ακύρωση συναλλαγών ή την επανεκτέλεσή τους σε παλαιότερο κύριο αρχείο.
Επεξεργασία αρχείων στη C
Η επεξεργασία αρχείων στη C γίνεται με βάση συναρτήσεις του
αφηρημένου τύπου δεδομένων FILE * που ορίζονται
στην επικεφαλίδα stdio.h.
Για να αποκτήσει το πρόγραμμα πρόσβαση σε ένα αρχείο πρέπει να
καλέσει τη συνάρτηση:
fopen(μονοπάτι αρχείου, τύπος πρόσβασης)
Η συνάρτηση επιστρέφει μια τιμή τύπου FILE * την οποία το πρόγραμμα
χρησιμοποιεί για πρόσβαση στο αρχείο.
Αν η πρόσβαση στο αρχείο δεν είναι δυνατή (π.χ.
το αρχείο στο οποίο ζητήθηκε ανάγνωση δεν υπάρχει,
ένας κατάλογος από το μονοπάτι δεν υπάρχει,
το αρχείο το οποίο ζητήθηκε εγγραφή δεν το επιτρέπει)
τότε η συνάρτηση fopen επιστρέφει την τιμή NULL.
Ο τύπος πρόσβασης μπορεί να είναι ένας από τους παρακάτω:
Στο τέλος της επεξεργασίας του αρχείου πρέπει να καλέσουμε τη
συνάρτηση fclose(f) (όπου f η τιμή που επέστρεψε η fopen)
για να δηλώσουμε στη βιβλιοθήκη και το λειτουργικό σύστημα
να απελευθερώσουν τους πόρους που είχαν δεσμευτεί για την
επεξεργασία του αρχείου.
Σειριακή επεξεργασία αρχείων ASCII στη C
Η σειριακή επεξεργασία αρχείων που περιέχουν χαρακτήρες ASCII
στη μορφή που τους διαβάζουν και γράφουν οι άνθρωποι γίνεται
με βάση τις παρακάτω συναρτήσεις:
- fprintf(FILE *stream, char *format, ...)
- Τυπώνει φορμαρισμένα σε αρχείο.
- fscanf(FILE *stream, char *format, ...)
- Διαβάζει φορμαρισμένα από αρχείο.
- fgetc(FILE *stream)
- Διαβάζει έναν χαρακτήρα από αρχείο.
- fputc(char c, FILE *stream)
- Γράφει έναν χαρακτήρα σε αρχείο.
- feof(FILE *stream)
- Επιστρέφει αληθές αν έχει ανιχνευτεί το τέλος του
αρχείου.
Οι παραπάνω συναρτήσεις είναι αντίστοιχες με τις printf, scanf, getchar, putchar,
μόνο που αντί για την είσοδο και έξοδο του προγράμματος δουλεύουν σε αρχεία.
Το παρακάτω πρόγραμμα γράφει στο αρχείο codes.txt τους χαρακτήρες
ASCII που διαβάζονται και τους αντίστοιχους κωδικούς τους:
#include <stdio.h>
main()
{
FILE *f;
int i;
f = fopen("codes.txt", "w");
for (i = ' '; i < '~'; i++)
fprintf(f, "Character: %c code:%d\n", i, i);
fclose(f);
}
Σημείωση: οι συναρτήσεις getc και putc είναι γρήγορες εκδόσεις των
gfetc και fputc.
Σειριακή επεξεργασία κωδικοποιημένων αρχείων στη C
Για λόγους απόδοσης συχνά τα αρχεία δεν περιέχουν παράσταση των
τιμών των δεδομένων με τη μορφή που τα εισάγουν και τα διαβάζουν
οι άνθρωποι (αρχεία ASCII (ASCII files)),
αλλά με τη μορφή που φυλάσσονται στη μνήμη του υπολογιστή
(δυαδικά αρχεία (binary files)).
Ο τρόπος αυτός φύλλαξης έχει τις παρακάτω επιπτώσεις:
- το πρόγραμμα είναι ταχύτερο μια και δεν απαιτείται μετατροπή
μεταξύ της εσωτερικής και της εξωτερικής μορφής παράστασης.
- η αποσφαλμάτωση του προγράμματος και των αρχείων του
είναι πιο δύσκολη μια και τα δυαδικά αρχεία δεν μπορούν να διαβαστούν
εύκολα από τυποποιημένα εργαλεία του συστήματος όπως ο διορθωτής.
- τα δυαδικά αρχεία δεν μπορούν να μεταφερθούν ανάμεσα σε υπολογιστές
διαφορετικής αρχιτεκτονικής (π.χ. από Intel Pentium σε DEC Alpha) μια
και η εσωτερική παράσταση των δεδομένων μεταξύ των αρχιτεκτονικών συνήθως
διαφέρει.
- Τα δυαδικά αρχεία καταλαμβάνουν λιγότερο χώρο από τα αρχεία ASCII.
Μεταφορά στοιχείων μεταξύ της κεντρικής μνήμης και αρχείων γίνεται
με τις συναρτήσεις:
- fread(void *ptr, size_t size, size_t nitems, FILE *stream)
-
Μεταφέρει nitems στοιχεία μεγέθους size από το αρχείο f στη θέση μνήμης ptr.
- fwrite(void *ptr, size_t size, size_t nitems, FILE *stream)
-
Μεταφέρει nitems στοιχεία μεγέθους size από τη θέση μνήμης ptr στο αρχείο f.
Το παρακάτω παράδειγμα γράφει τον πίνακα tbl στο αρχείο f:
int tbl[100];
fwrite(tbl, sizeof(int), 100, f);
Επεξεργασία αρχείων τυχαίως προσπέλασης στη C
Η βιβλιοθήκη της C μας δίνει τη δυνατότητα μετακίνησης και σε τυχαία
σημεία του αρχείου με βάση τις συναρτήσεις fseek και ftell:
- int fseek(FILE * f, long pos, int whence);
-
Ορίζει ως επόμενη θέση για ανάγνωση ή εγγραφή στο αρχείο f
τη θέση pos.
Η θέση ορίζεται ανάλογα με τη σταθερά που θα οριστεί στη whence:
- SEEK_CUR
- από την τρέχουσα θέση στο αρχείο,
- SEEK_END
- από το τέλος του αρχείου,
- SEEK_SET
- από την αρχή του αρχείου.
Η fseek επιστρέφει -1 αν η θέση που δώθηκε δεν είναι σωστή, αλλιώς
επιστρέφει 0.
Το παρακάτω παράδειγμα μεταφέρει τη θέση ανάγνωσης στον 10ο ακέραιο
του αρχείου f:
fseek(f, 10 * sizeof(int), SEEK_SET);
- long ftell(FILE *f)
- Επιστρέφει την τρέχουσα θέση ανάγνωσης/εγγραφής
στο αρχείο f.
Βιβλιογραφία
- Χρήστος Κοίλιας
Δομές Δεδομένων και Οργανώσεις Αρχείων. σ. 208-221
Εκδόσεις Νέων Τεχνολογιών, 1993.
- Peter Pin-Shan Chen.
The entity-relationship model --- toward a unified view of data.
ACM Transactions on Database Systems, 1(1):9-36, March 1976.
- Henry F. Korth and Abraham Silberschatz.
Database System Concepts.
McGraw-Hill, third edition, 1996.
- Brian W. Kernighan, Dennis M. Ritchie
Η γλώσσα προγραμματισμού C. σ. 337-349
Δεύτερη έκδοση.
Κλειδάριθμος, 1988.
- Brian W. Kernighan and
Dennis M. Ritchie.
The C
Programming Language, pages 241-258.
Prentice-Hall, second edition, 1988.
- P. J. Plauger.
The Standard C Library.
Prentice Hall, 1992.
Ασκήσεις
Άσκηση 7
- Να υλοποιηθεί σε C το πρόγραμμα addphone
το οποίο ζητά από το χρήστη ένα όνομα και ένα τηλέφωνο και
τα προσθέτει σε αρχείο
καθώς και το πρόγραμμα getphone το οποίο ζητά από το
χρήστη ένα όνομα και αν αυτό βρίσκεται στο αρχείο
τυπώνει το τηλεφωνό του.
Παράδειγμα:
C>addphone
Name:EKAB
Phone:166
C>getphone
Name:EKAB
Phone=166