Documents
Resources
Learning Center
Upload
Plans & pricing Sign in
Sign Out

Εισαγωγ_ στο Unix - LPIS

VIEWS: 0 PAGES: 90

									       Αρχεία

       Γλώσσα C & Unix
       Τμήμα Πληροφορικής, ΑΠΘ
       B’ εξάμηνο

lpis.csd.auth.gr/curriculum/C+Unix/UNCL202.html
Εισαγωγή

¡ Υπάρχουν    δύο είδη αρχείων
 l αρχεία   κειμένου
 l δυαδικά   αρχεία




                                 2
    Δυαδικά Αρχεία
¡   Μοιάζουν πολύ με πίνακες από δομές
    l   Οι δομές αποθηκεύονται σε ένα αρχείο στο δίσκο
        και όχι σε ένα πίνακα στη μνήμη
¡   Μπορούν να δημιουργηθούν πολύ μεγάλες
    συλλογές από τέτοιες δομές
    l   Με τον περιορισμό του ελεύθερου χώρου στο δίσκο
¡   Οι δομές αποθηκεύονται μόνιμα και είναι
    πάντα διαθέσιμες
¡   Μειονέκτημα: αργός χρόνος προσπέλασης
    των δεδομένων εξαιτίας της ταχύτητας
    πρόσβασης στο δίσκο
                                                         3
    Αρχεία Κειμένου

¡   Σειρές από χαρακτήρες
    αποθηκευμένους στο σκληρό δίσκο
¡   Tο περιεχόμενο τους είναι άμεσα
    αναγνώσιμο
¡   Μπορούν να ανοιχτούν με ένα
    οποιοδήποτε πρόγραμμα ανάγνωσης
    αρχείων κειμένου
    l   Notepad, WordPad, TextPad, Word, κτλ),

                                                 4
Διαφορές Δυαδικών Αρχείων –
Αρχείων Κειμένου (1/2)

¡   Στα δυαδικά αρχεία μπορούμε να
    πάμε απευθείας σε οποιαδήποτε δομή
    μέσα στο αρχείο
    l   Όπως μέσα σε ένα πίνακα
    l   «Τυχαία προσπέλαση»
    l   Μπορούμε να αλλάξουμε τα περιεχόμενα
        μιας δομής οπουδήποτε μέσα στο αρχείο
        και οποτεδήποτε.

                                                5
    Διαφορές Δυαδικών Αρχείων –
    Αρχείων Κειμένου (2/2)
¡   Τα δυαδικά αρχεία έχουν γρηγορότε-
    ρους χρόνους ανάγνωσης και εγγραφής
    l   Mια «δυαδική εικόνα» της εγγραφής
        αποθηκεύεται απευθείας από τη μνήμη στο
        δίσκο και το αντίθετο
¡   Σε ένα αρχείο κειμένου, όλα πρέπει να
    μετατραπούν από δυαδική μορφή σε
    κείμενο και το αντίθετο
    l   Παίρνει χρόνο


                                              6
    Ο Δείκτης Αρχείου
¡   Δείχνει σε πληροφορίες που ορίζουν
    διάφορες λεπτομέρειες σχετικά με το αρχείο
    l   Π.χ. όνομα, κατάσταση, τρέχουσα θέση στο αρχείο
¡   Συνδέεται με ένα συγκεκριμένο αρχείο στο
    δίσκο
    l   Χρησιμοποιείται από το κανάλι που είναι
        συνδεδεμένο με το αρχείο για να πληροφορήσει τις
        συναρτήσεις εισόδου/εξόδου πού να εκτελέσουν τις
        λειτουργίες τους
¡   Είναι μια μεταβλητή δείκτης τύπου FILE
    l   Ορισμένος στη βιβλιοθήκη stdio.h.
                       FILE *fp;
                                                     7
    Συνάρτηση fopen() - Είσοδος

¡   Ανοίγει ένα αρχείο για χρήση και επιστρέφει
    έναν δείκτη αρχείου προς αυτό το αρχείο.
FILE *fopen(const char *onoma_arheiou,
           const char *katastasi);
¡   onoma_arheiou º συμβολοσειρά με το όνομα
    του αρχείου στο σύστημα
    l   Μπορεί να περιλαμβάνει και τη διαδρομή στο δίσκο
¡   katastasi º συμβολοσειρά που περιέχει την
    επιθυμητή κατάσταση ανοίγματος

                                                      8
  Επιτρεπτές Τιμές της Κατάστασης
  Ανοίγματος Αρχείου
Κατάσταση    Ερμηνεία
"r" ή "rt"   Άνοιγμα αρχείου κειμένου για ανάγνωση
               (R)
"w" ή "wt"   Δημιουργία αρχείου κειμένου για
               εγγραφή (W)
"a" ή "at"   Άνοιγμα αρχείου κειμένου για προσθήκη
               (A)
"rb"         Άνοιγμα δυαδικού αρχείου για R
"wb"         Δημιουργία δυαδικού αρχείου για W
"ab"         Άνοιγμα δυαδικού αρχείου για A
"r+"    ή    Άνοιγμα αρχείου κειμένου για R/W
  "r+t"
"w+"    ή    Δημιουργία αρχείου κειμένου για R/W
  "w+t"
                                                     9
    Συνάρτηση fopen() - Έξοδος

¡   Επιστρέφει έναν δείκτη τύπου FILE
    (δείκτης αρχείου)
¡   Αυτός ο δείκτης συνδέεται μοναδικά
    με το αρχείο
¡   Χρησιμοποιείται από τις περισσότερες
    συναρτήσεις του συστήματος αρχείων
    της C
¡   Δεν θα πρέπει να αλλάζει η τιμή
    αυτού του δείκτη με τον κώδικα!
                                       10
    Άνοιγμα Αρχείου
¡   Ένα αρχείο μπορεί να ανοιχτεί είτε σαν
    δυαδικό αρχείο είτε σαν αρχείο κειμένου
¡   Κατά την ανάγνωση ενός αρχείου κειμένου:
    l   Οι χαρακτήρες enter '\r', μετατρέπονται σε αλλαγές
        γραμμής '\n' καθώς εμφανίζονται στην οθόνη.
¡   Κατά την εγγραφή ενός αρχείου κειμένου
    συμβαίνει το αντίθετο.
    l   Οι αλλαγές γραμμής μετατρέπονται σε χαρακτήρες
        enter.
¡   Οι μετατροπές αυτές δεν συμβαίνουν στα
    δυαδικά αρχεία.

                                                        11
Άνοιγμα Αρχείου - Παράδειγμα

¡   Άνοιγμα αρχείου για εγγραφή με το
    όνομα test:


    FILE *fp;
    fp = fopen("test", "w");




                                        12
    Άνοιγμα Αρχείου – Αποφυγή Λαθών
FILE *fp;
if ((fp = fopen("test", "w")) == NULL) {
  puts("Η δημιουργία του αρχείου δεν είναι εφικτή!");
  exit(1);
}
¡ Πιθανά λάθη ανοίγματος αρχείου
    l   Δεν υπάρχει το αρχείο προς ανάγνωση, δεν υπάρχει
        χώρος στο δίσκο για δημιουργία αρχείου, κ.ά.
¡   Το NULL είναι 0
    l   Ορίζεται στην stdio.h με #define


                                                     13
    Άνοιγμα Αρχείου - Περιπτώσεις
¡   Αν ένα αρχείο ανοιχτεί για εγγραφή
    l   Αν το αρχείο ήδη υπάρχει, τότε σβήνεται
    l   Αν το αρχείο δεν υπάρχει, τότε δημιουργείται
¡   Για να ανοίξει ένα αρχείο για ανάγνωση,
    πρέπει το αρχείο αυτό να υπάρχει ήδη
    l   Αν δεν υπάρχει θα επιστραφεί ένα λάθος
¡   Αν ένα αρχείο ανοιχτεί για R/W
    l   Αν το αρχείο ήδη υπάρχει, τότε δεν σβήνεται
    l   Αν το αρχείο δεν υπάρχει, τότε δημιουργείται

                                                       14
    Συνάρτηση fclose()
¡   Κλείνει ένα κανάλι το οποίο ανοίχτηκε με μια
    προηγούμενη κλήση της fopen()
¡   Γράφει τα δεδομένα που απομένουν στην
    ενδιάμεση μνήμη του δίσκου στο αρχείο
    l   Μετά κλείνει το αρχείο σύμφωνα με τις τυπικές
        απαιτήσεις του λειτουργικού συστήματος
¡   Το λειτουργικό σύστημα επιβάλει ένα όριο
    αριθμού αρχείων που είναι ανοιχτά ανά πάσα
    στιγμή
    l   Επομένως αν κάποιο αρχείο δεν χρειάζεται, καλό
        θα ήταν να κλείσει πριν ανοίξει κάποιο άλλο

                                                        15
    Συνάρτηση fclose()
int fclose(FILE *fp);
¡ fp είναι ο δείκτης αρχείου που επέστρεψε η
  fopen()
¡ Αν η fclose() εκτελεστεί
    l   Επιτυχώς, τότε επιστρέφει 0
    l   Ανεπιτυχώς, τότε επιστρέφει τη σταθερά EOF
¡   Η fclose() αποτυγχάνει στις (σπάνιες)
    περιπτώσεις όπου:
    l   ένα αρχείο ήταν ανοιγμένο από δισκέτα η οποία δεν
        υπάρχει πλέον στον οδηγό δισκέτας, ή
    l   σε περίπτωση που ο δίσκος ή η δισκέτα δεν έχουν
        άλλο χώρο

                                                      16
    Συνάρτηση fputc()
¡ Εγγραφή χαρακτήρων σε ένα αρχείο το οποίο
  είχε ανοιχτεί προηγουμένως για εγγραφή
  μέσω της fopen()
int fputc(int ch, FILE *fp);
¡ fp: ο δείκτης αρχείου που επιστράφηκε από
  την fopen()
    l   Ο δείκτης αρχείου πληροφορεί την συνάρτηση σε
        ποιο αρχείο δίσκου να γράψει.
¡   ch: ο χαρακτήρας που θα γραφτεί
¡   Αν η συνάρτηση fputc()
    l   Επιτύχει, τότε επιστρέφει το χαρακτήρα που έγραψε
    l   Αποτύχει, τότε επιστρέφει EOF (End Of File)
                                                        17
    Συνάρτηση fgetc()

¡ Ανάγνωση χαρακτήρων από ένα κανάλι
  το οποίο έχει ανοιχτεί για ανάγνωση με
  fopen()
int fgetc(FILE *fp);
¡ fp: ο δείκτης αρχείου που
  επιστράφηκε από την fopen()
¡ Επιστρέφει τη σταθερά EOF όταν ο
  δείκτης αρχείου δείχνει το τέλος του
  αρχείου
                                     18
    Γιατί int και όχι char;
¡   Για ιστορικούς λόγους, στην fgetc(), ο
    χαρακτήρας ch δηλώνεται int, και όχι
    char
    l   Χρησιμοποιείται μόνο το χαμηλότερης
        τάξης byte, άρα χρησιμοποιείται για την
        εγγραφή χαρακτήρων μόνο.
¡   Το ίδιο συμβαίνει και στην fputc(), η
    οποία για ιστορικούς λόγους επιστρέφει
    τιμή int και όχι char
    l   Ουσιαστικά επιστρέφει χαρακτήρα αφού το
        υψηλής τάξης byte είναι 0
                                                  19
Παράδειγμα

¡   Ανάγνωση ενός αρχείου κειμένου από
    την αρχή μέχρι το τέλος του

    ch = fgetc(fp);

    while (ch != EOF) {
        ch = fgetc(fp);
    }


                                     20
    Συνάρτηση feof()

¡    Πληροφορεί αν έχει φτάσει το τέλος
     του αρχείου
int feof(FILE *fp);
¡    Επιστρέφει τιμή διαφορετική από 0 σε
     περίπτωση που έχει φτάσει το τέλος
     του αρχείου.
¡    Αλλιώς επιστρέφει 0.

                                          21
  Παράδειγμα Ανάγνωσης Αρχείου Μέχρι
  το Τέλος του
char ch;
FILE *fp;

if ((fp = fopen("arheio","r")) == NULL)
{
    puts("Το άνοιγμα του αρχείου απέτυχε!");
    exit(1);
}

while (!feof(fp))
    ch = fgetc(fp);
                                         22
    Συνάρτηση ferror()
¡  Ανιχνεύει αν μια λειτουργία αρχείου είχε
   λανθασμένο αποτέλεσμα
int ferror(FILE *fp);
¡  Επιστρέφει αληθή τιμή, αν έγινε λάθος κατά
   τη διάρκεια της τελευταίας λειτουργίας επί
   του αρχείου που δείχνει ο δείκτης αρχείου fp
    l   Αλλιώς επιστρέφει ψευδή τιμή
¡   Επειδή κάθε λειτουργία επί αρχείου αλλάζει
    την κατάσταση λάθους, θα πρέπει η
    ferror() να χρησιμοποιείται αμέσως μετά
    την λειτουργία που θέλουμε να ελέγξουμε
                                             23
    Συναρτήσεις Διαχείρισης Αρχείων
    Κειμένου – fputs() και fgets()

¡   Χρησιμοποιούνται για εγγραφή και
    ανάγνωση συμβολοσειρών σε αρχεία
    κειμένου

int fputs (char *str, FILE *fp);
char *fgets(char *str, int num,
            FILE *fp);


                                       24
    Συνάρτηση fputs()
¡   Γράφει το αλφαριθμητικό str στο
    αρχείο που σχετίζεται με τον δείκτη fp
¡   Επιστρέφει
    l   EOF εάν συναντήσει ένα σφάλμα
    l   μη-αρνητική τιμή εάν είναι επιτυχής
¡   Ο χαρακτήρας ‘\0’ που τερματίζει το
    str δεν γράφεται
¡   Δεν προσθέτει αυτόματα ένα ζεύγος
    χαρακτήρων αλλαγής γραμμής
     l Αντίθετα με τη συνάρτηση puts()
                                              25
Συνάρτηση fgets()               (1/2)

¡   Διαβάζει χαρακτήρες από το αρχείο fp
    στο αλφαριθμητικό str
¡   Η ανάγνωση συνεχίζεται μέχρι να
    l   διαβαστούν num-1 χαρακτήρες, ή
    l   βρεθεί ένας χαρακτήρας νέας γραμμής, ή
    l   φτάσει το τέλος του αρχείου.
¡   Το αλφαριθμητικό τερματίζεται με τον
    χαρακτήρα ‘\0’

                                             26
Συνάρτηση fgets()                (2/2)


¡   Ο χαρακτήρας νέας γραμμής
    διατηρείται
    l   Αντίθετα με την gets()

¡   Η συνάρτηση επιστρέφει
    l   το str, εάν είναι επιτυχής
    l   έναν κενό δείκτη, εάν συμβεί σφάλμα



                                              27
    Συναρτήσεις fprintf(), fscanf()
¡   Λειτουργούν ακριβώς όπως οι printf(),
    scanf()
    l   Χρησιμοποιούνται με αρχεία
int fprintf(FILE *fp, const char
                            *fmt_string, …);
int fscanf(FILE *fp, const char
                            *fmt_string, …);
¡  Είναι ο ευκολότερος τρόπος για εγγραφή και
   ανάγνωση δεδομένων από ένα αρχείο
   κειμένου, αλλά όχι ο πιο αποδοτικός
    l   Κάθε κλήση «κοστίζει» κάτι παραπάνω
                                              28
    Μέτρηση Συχνότητας Εμφάνισης
    Λέξεων σε Κείμενο – Παραλλαγή 2

¡   Θέλουμε το πρόγραμμα να διαβάζει το
    κείμενο από αρχείο και να αποθηκεύει
    τα αποτελέσματα σε αρχείο
¡   Τα ονόματα των αρχείων τα ζητάει από
    το χρήστη στην αρχή του
    προγράμματος
¡   Αν για οποιοδήποτε λόγο δεν μπορεί να
    «ανοίξει» κάποιο αρχείο χρησιμοποιεί
    τα stdin, stdout
                                       29
  Κυρίως Πρόγραμμα - main()
int main () {
 struct tnode *root = NULL;     Ονόματα
 char word[MAXWORD];            αρχείων
 char fileIN[50],fileOUT[50];
 FILE *fin,*fout;                Δείκτες
                                 αρχείων
 printf("Input filename: ");
 scanf("%s",fileIN);            Εισαγωγή
 printf("Output filename: ");   ονομάτων
 scanf("%s",fileOUT);           αρχείων


                                      30
  Κυρίως Πρόγραμμα - main()
if ((fin = fopen(fileIN, "r")) == NULL)
{
                                      • Άνοιγμα αρχείου
  printf("File %s cannot be opened! εισόδου
         Exiting...\n",fileIN);       • Αν δεν ανοίγει,
  exit(1);                              τερματισμός
}
if ((fout = fopen(fileOUT, "w")) == NULL)
{
  printf("File %s cannot be opened! Using stdout
         instead...\n",fileOUT);
  fout = stdout;         • Άνοιγμα αρχείου εξόδου
}                        • Αν δεν ανοίγει, χρήση
                           πρότυπης εξόδου
                                                    31
  Κυρίως Πρόγραμμα - main()
while (getword(fin,word,MAXWORD) != EOF)
  if (isalpha(word[0]))
                                 Είσοδος
   root = addtree(root, word);
                                από αρχείο
treeprint(fout,root);
fclose(fin);
                  Κλείσιμο      Εκτύπωση
fclose(fout);     αρχείων       σε αρχείο
return 0;
}



                                        32
    Συνάρτηση getword() - Αλλαγές
int getword(FILE *fp,char *word, int lim) {
  int c; char *w = word;

    while (isspace(c = fgetc(fp)));
    if (c != EOF) *w++ = c;
    if (!isalpha(c)) {
      *w = '\0';
      return c; }
    for ( ; --lim > 0; w++)
      if (!isalnum(*w = fgetc(fp))) {
        ungetc(*w,fp);
        break;   }
    *w = '\0';
    return word[0];
}
                                              33
  Συνάρτηση treeprint() - Αλλαγές

void treeprint(FILE *fp,struct tnode *p)
{
  if (p != NULL) {
    treeprint(fp,p->left);
    fprintf(fp,"%4d %s\n",p->count,
                                p->word);
    treeprint(fp,p->right);
  }
}
                                     34
Μέτρηση Συχνότητας Εμφάνισης
Λέξεων σε Κείμενο – Παραλλαγή 3

¡ Θέλουμε   το πρόγραμμα να
 διαβάζει τα ονόματα των
 αρχείων εισόδου-εξόδου από τη
 γραμμή διαταγών
¡ Π.χ.   cw in.txt out.txt


                                  35
  Κυρίως Πρόγραμμα - main()
int main (int argc, char *argv[]) {
  struct tnode *root = NULL;
  char word[MAXWORD];               Αριθμός
  FILE *fin,*fout;                  Πίνακας
                                    παραμέτρων
                                      παραμέτρων
 if (argc == 1) {          Αν δεν υπάρχουν παράμετροι,
   fin = stdin;            τότε είσοδος/έξοδος είναι οι
   fout = stdout;}         πρότυπες
 else if (argc == 2) {
   if ((fin = fopen(argv[1], "r")) == NULL) {
     printf("File %s cannot be opened! Exiting...\n",
            argv[1]);
     exit(1);
                      Αν υπάρχει 1 παράμετρος,
   }
                      τότε αυτή είναι είσοδος.
   fout = stdout;
                      Η έξοδος είναι η πρότυπη
 }
                                                    36
     Κυρίως Πρόγραμμα - main()
else {                Υπάρχουν τουλάχιστον 2 παράμετροι
  if ((fin = fopen(argv[1], "r")) == NULL) {
    printf("File %s cannot be opened! Exiting...\n",
           argv[1]);
    exit(1);             Η πρώτη είναι το αρχείο εισόδου
    }
    if ((fout = fopen(argv[2], "w")) == NULL) {
      printf("File %s cannot be opened! Using stdout instead...\n",
             argv[2]);
      fout = stdout;
                            Η δεύτερη είναι το αρχείο εξόδου
    }
}
                                                               37
    Κυρίως Πρόγραμμα - main()
while (getword(fin,word,MAXWORD)!=EOF)
    if (isalpha(word[0]))
     root = addtree(root, word);
treeprint(fout,root);
fclose(fin);
fclose(fout);
                   Καμία αλλαγή από την
return 0;          προηγούμενη εκδοχή
}                  του προγράμματος


                                          38
    Εκτύπωση Μηνυμάτων Σφάλματος
¡ Για την εκτύπωση μηνυμάτων
  σφάλματος χρησιμοποιήθηκε η printf
printf("File %s cannot be opened!
  Exiting...\n",argv[1]);
¡ Το μήνυμα τυπώνεται στην πρότυπη
  έξοδο
¡ Καλύτερα να χρησιμοποιηθεί το ειδικό
  κανάλι για μηνύματα λάθους stderr
fprintf(stderr,"File %s cannot be
  opened! Exiting...\n",argv[1]);
                                     39
    Μέτρηση Συχνότητας Εμφάνισης
    Λέξεων σε Κείμενο – Παραλλαγή 4
¡   Μπορούν να υπάρχουν πολλά αρχεία
    εισόδου, αλλά μόνο ένα αρχείο εξόδου
    l   cw text1.txt text2.txt out.txt
    l   cw text1.txt out.txt
¡   Όταν υπάρχει μία παράμετρος, αυτή
    είναι αρχείο εισόδου
    l   cw text1.txt (έξοδος στην οθόνη)
¡   Όταν δεν υπάρχουν παράμετροι, τότε
    είσοδος/έξοδος είναι οι πρότυπες

                                           40
  Κυρίως Πρόγραμμα - main()
int main (int argc, char *argv[]) {
  struct tnode *root = NULL;
  char word[MAXWORD];
   FILE *fin,*fout;          Όριο αρχείων εισόδου στις
   int i,limit;              παραμέτρους – η τελευταία
                             είναι το αρχείο εξόδου
 limit = argc-1;
 if (argc == 1) {                   Αν δεν υπάρχουν
    fin=stdin;                      παράμετροι, τότε
    fout=stdout;                    είσοδος/έξοδος είναι
 }                                  οι πρότυπες
   else if (argc == 2) {
    fout=stdout;
    limit = 2;    Αν υπάρχει 1 παράμετρος,
 }                τότε αυτή είναι είσοδος.
                  Η έξοδος είναι η πρότυπη
                                                      41
  Κυρίως Πρόγραμμα - main()
else {
  if ((fout = fopen(argv[argc-1], "w")) ==
NULL) {
    printf("File %s cannot be opened! Using stdout
instead...\n", argv[argc-1]);
    fout = stdout;
  }
}            •Υπάρχουν τουλάχιστον 2
             παράμετροι.
            •Η έξοδος είναι η τελευταία

                                               42
    Κυρίως Πρόγραμμα - main()
for(i=1; i<limit; i++) {
    if ((fin = fopen(argv[i], "r")) == NULL)
        printf("File %s cannot be opened!\n",argv[i]);
    else {
        while (getword(fin, word, MAXWORD) != EOF)
         if (isalpha(word[0]))
           root = addtree(root, word);
        fclose(fin);
                           • Κάθε φορά που τελειώνει ένα
    }
                  •Βρόχος που ανοίγει ένα-ένα
                             αρχείο εισόδου, κλείνεται πριν
}                            ανοίξει το επόμενο
                   όλα τα αρχεία εισόδου και τα
                   τοποθετεί στο δένδρο                  43
  Κυρίως Πρόγραμμα - main()
if (argc == 1) {
  while (getword(fin,word,MAXWORD)!=EOF)
    if (isalpha(word[0]))
      root = addtree(root, word);
}
treeprint(fout,root);
fclose(fout); • Το δένδρο περιέχει τα αποτελέσματα
                από όσα αρχεία και αν παράμετροι,
                • Όταν δεν υπάρχουν προέρχονται
return 0;
              • Ηο βρόχος δεν εκτελείται (αφού
                   εκτύπωση στο αρχείο εξόδου
}                 δεν υπάρχουν στο τέλος
                γίνεται μία φορά αρχεία εισόδου)
                  • Το διάβασμα γίνεται από stdout

                                                 44
    Συναρτήσεις Διαχείρισης Δυαδικών
    Αρχείων
¡ Οι συναρτήσεις fread() και fwrite()
  χρησιμοποιούνται για την ανάγνωση
  και εγγραφή οποιουδήποτε τύπου
  δεδομένων χρησιμοποιώντας την
  δυαδική του αναπαράσταση
size_t fread(void *buffer, size_t
  size, size_t num, FILE *fp);
size_t fwrite(void *buffer, size_t
  size, size_t num, FILE *fp);

                                       45
    Συνάρτηση fread()
size_t fread(void *buffer, size_t
  size, size_t num, FILE *fp);
¡   Διαβάζει από το αρχείο στο οποίο
    δείχνει ο δείκτης fp
    l   num (το πλήθος) στοιχεία δεδομένων
    l   με μέγεθος size το καθένα
    l   στην περιοχή προσωρινής αποθήκευσης
        που δείχνει ο δείκτης buffer

                                              46
    Συνάρτηση fread()
size_t fread(void *buffer, size_t
  size, size_t num, FILE *fp);
¡   Επιστρέφει τον αριθμό των
    αντικειμένων που τελικά διαβάστηκαν
    l   Εάν αυτή η τιμή είναι μικρότερη από num,
        σημαίνει ότι έφτασε το τέλος του αρχείου ή
        συνέβη κάποιο σφάλμα
    l   Μπορεί να χρησιμοποιηθούν οι feof(),
        ferror() για να εξακριβωθεί τι συνέβη

                                                47
    Συνάρτηση fwrite()
size_t fwrite(void *buffer, size_t
  size, size_t num, FILE *fp);
¡   Γράφει στο αρχείο στο οποίο δείχνει ο
    δείκτης fp
    l   num το πλήθος στοιχεία δεδομένων
    l   με μέγεθος size το καθένα
    l   τα οποία παίρνει από την περιοχή
        προσωρινής αποθήκευσης στην οποία
        δείχνει ο δείκτης buffer

                                            48
    Συνάρτηση fwrite()
size_t fwrite(void *buffer, size_t
  size, size_t num, FILE *fp);
¡   Επιστρέφει το πλήθος των αντικειμένων
    που τελικά έγραψε
    l   Εάν αυτή η τιμή είναι μικρότερη από num,
        σημαίνει ότι συνέβη κάποιο σφάλμα




                                                   49
  Παράδειγμα fread(), fwrite()
#include <stdio.h>
                       Δημιουργώ μια δομή με έναν
int main(void) {       ακέραιο και έναν χαρακτήρα
  FILE *fp;
  struct mystruct {
                       Γράφω σε αρχείο τη δομή
    int i;
    char ch;
  } s, t;

 if ((fp = fopen("TEST.$$$", "wb")) == NULL) {
   fprintf(stderr, "Cannot open output file.\n");
   return 1; }
 s.i = 5;
 s.ch = 'A';
 fwrite(&s, sizeof(s), 1, fp);
 fclose(fp);
                                                    50
    Παράδειγμα fread(), fwrite()
    if ((stream = fopen("TEST.$$$", "rb")) == NULL) {
        fprintf(stderr, "Cannot open input file.\n");
        return 1;
    }
    fread(&t,sizeof(t),1,stream);
    fclose(stream);
  printf("I have read one character: %c, and one
integer: %d.\n", t.ch, t.i);
    return 0;
}                       Διαβάζω τη δομή από το αρχείο



                                                        51
    Είσοδος/Έξοδος Τυχαίας
    Προσπέλασης – Συνάρτηση fseek()

¡   Μπορεί να πραγματοποιηθεί εγγραφή
    και ανάγνωση με τυχαία προσπέλαση
    χρησιμοποιώντας την συνάρτηση
    fseek()
¡   Τοποθετεί το δείκτη θέσης αρχείου σε
    κάποιο σημείο



                                           52
  Είσοδος/Έξοδος Τυχαίας
  Προσπέλασης – Συνάρτηση fseek()
int fseek(FILE *fp, long num_bytes,
                                 int origin);
¡ fp είναι ο δείκτης αρχείου

¡ num_bytes είναι ο αριθμός των bytes έπειτα
  από τη θέση origin που θα μετακινηθεί ο
  δείκτης θέσης αρχείου
¡ origin είναι μια σταθερά που περιγράφει
  κάποια θέση μέσα στο αρχείο
¡ Επιστρέφει
  l   0 αν εκτελεστεί με επιτυχία
  l   Ένα διαφορετικό νούμερο αν αποτύχει
                                            53
Σταθερές origin


 origin           Σταθερά
 Αρχή του         SEEK_SET
 αρχείου
 Τρέχουσα θέση SEEK_CUR
 Τέλος αρχείου SEEK_END


                             54
    Χρήση fseek()

¡   Η χρήση της fseek() με αρχεία
    κειμένου δεν συνιστάται
¡   Oι μετατροπές χαρακτήρων προκαλούν
    λάθη που σχετίζονται με την θέση των
    χαρακτήρων στο αρχείο
¡   Προτείνεται η αποκλειστική χρήση της
    fseek() με δυαδικά αρχεία

                                       55
    Συνάρτηση ftell()

¡   Επιστρέφει την τρέχουσα θέση στο
    αρχείο, μετρημένη σε bytes από την
    αρχή του αρχείου (δυαδικά αρχεία)
long int ftell(FILE *fp);
¡   Η τιμή που επιστρέφει μπορεί να
    χρησιμοποιηθεί από την fseek
¡   Επιστρέφει -1L σε περίπτωση λάθους

                                         56
    Παράδειγμα Χρήσης fseek()-
    ftell() – Μέγεθος Αρχείου
long filesize(FILE *fp) {
   long curpos, length;
                            Πηγαίνουμε στο
                             Κρατάμε την
                           τέλος του αρχείου
                          τρέχουσα θέση για
     curpos = ftell(fp);   να επιστρέψουμε
                                 Το μήκος σε
     fseek(fp, 0L, SEEK_END); bytes του
                                   αρχείου
     length = ftell(fp);
     fseek(fp, curpos, SEEK_SET);
     return length;
}            Επιστρέφουμε τον pointer του
             αρχείου στην αρχική του θέση   57
  Παράδειγμα Χρήσης fseek()-
  ftell() – Μέγεθος Αρχείου (main)
int main(void) {
   FILE *fp;

   fp = fopen("MYFILE.TXT", "w+");
   fprintf(fp, "This is a test");
   printf("Filesize of MYFILE.TXT is %ld
bytes\n", filesize(fp));
   fclose(fp);
   return 0;
}
                                      58
Άλλες Συναρτήσεις Διαχείρισης
Αρχείων

¡ remove()

¡ rewind()

¡ rename()




                                59
    Συνάρτηση remove()

¡   Διαγράφει το αρχείο, το όνομα του
    οποίου της δίνεται ως παράμετρος.
int remove(const char *filename);
¡   Επιστρέφει 0 αν επιτύχει, και
    διαφορετική τιμή αλλιώς.



                                        60
  Παράδειγμα Διαγραφής Αρχείου
#include <stdio.h>
void main(void){
 char onoma_arheiou[80];
  printf("Δώσε το όνομα του αρχείου που θες να
διαγράψεις: ");
  gets(onoma_arheiou);
  if (remove(onoma_arheiou)) {
    printf("Η διαγραφή του αρχείου δεν είναι
εφικτή!")
    exit(1);
  }
}
                                               61
Συνάρτηση rewind()

¡   Επαναφέρει το δείκτη θέσης
    αρχείου στην αρχή του
    αρχείου, το οποίο δίνεται ως
    παράμετρος.
void rewind(FILE *fp);


                                   62
    Παράδειγμα rewind()
#include <stdio.h>

int main(void) {
    FILE *fp;
    char *fname = “test.txt", first;

    fp = fopen(fname,"w+");
    fprintf(fp,"abcdefghijklmnopqrstuvwxyz");
    rewind(fp);
    fscanf(fp,"%c",&first);
    printf("The first character is: %c\n",first);
    fclose(fp);
    remove(fname);

    return 0;
}
                                                    63
    Συνάρτηση rename()
¡  Χρησιμοποιείται για την μετονομασία
   ενός αρχείου
void rename(char *oldname,
              char *newname);
¡ oldname το αρχικό όνομα του αρχείου

¡ newname το νέο όνομα του αρχείου

¡ Επιστρέφει
    l   0 εάν είναι επιτυχής
    l   Μη-μηδενική τιμή εάν συμβεί σφάλμα
                                             64
    Μέτρηση Συχνότητας Εμφάνισης
    Λέξεων σε Κείμενο – Παραλλαγή 5
¡   Θέλουμε το πρόγραμμα να διαβάζει ένα
    αρχείο κειμένου στην είσοδο και να
    αποθηκεύει τα αποτελέσματα σε ένα
    δυαδικό αρχείο εξόδου
    l   Π.χ. cw txt1.txt out.dat
¡   Αν το αρχείο εξόδου υπάρχει ήδη, τότε
    οι λέξεις του αρχείου εισόδου
    προστίθενται στις ήδη υπάρχουσες και
    τα συνολικά αποτελέσματα
    αποθηκεύονται ξανά στο αρχείο εξόδου
                                       65
  Κυρίως Πρόγραμμα (main)
int main (int argc, char *argv[]) {
   struct tnode *root = NULL;
   char word[MAXWORD];
   FILE *fin,*fout;         Προστασία για
   int count,i;             λάθος αριθμό
                             παραμέτρων
    if (argc < 3) {
        fprintf(stderr,"Program requires at least 1
input and 1 output file!\n");
        exit(1);
    }
                                                  66
                           Έλεγχος
                  Άνοιγμα αρχείου αν υπάρχει το
                    ως δυαδικό αρχείο εξόδου
  Κυρίως Πρόγραμμα (main)
else {
   if ((fout = fopen(argv[argc-1], "rb"))
!= NULL) {
       fread(word,MAXWORD,1,fout);
       fread(&count,sizeof(int),1,fout);
       while (!feof(fout)) {
          root=ins_tree(root,word,count);
          fread(word,MAXWORD,1,fout);
          fread(&count,sizeof(int),1,fout);
     }
     fclose(fout);         Εφόσον δεν έχει
   }                            Κλείσε το αρχείο
                         τελειώσει το αρχείο
}           Συνέχιζε να και τον μετρητή στο
            Βάλε τη λέξηδιαβάζεις λέξεις και
                ακεραίουςτο δυαδικό αρχείο
           Διάβασμα από δένδρο αρχείο
                           από το
             μιας λέξης και ενός ακεραίου      67
                 Για όλα τα αρχεία εισόδου

  Κυρίως Πρόγραμμα (main)
for(i=1; i<argc-1; i++) {
  if ((fin = fopen(argv[i], "r")) == NULL)
    fprintf(stderr,"File %s cannot be opened!\n",
                                        argv[i]);
  else {
    while (getword(fin,word,MAXWORD)!=EOF)
     if (isalpha(word[0]))
       root = addtree(root, word);
    fclose(fin);
  }                         Κλείσε το αρχείο και
}               Αν κάποιολέξεις του στο επόμενο
         Διάβασε όλες τιςπροχώρησεαρχείου
                           αρχείο δεν
                 ανοίγει, αγνόησέ δένδρο
           και καταχώρησέ τις στο το
                                              68
      Άνοιγμα του αρχείου εξόδου ως
       δυαδικό (σβήνοντας τα παλιά)
  Κυρίως Πρόγραμμα (main)
if ((fout = fopen(argv[argc-1], "wb")) ==
NULL) {
  fprintf(stderr,"File %s cannot be opened!\n",
                               argv[argc-1]);
  exit(2);
}
else {
  tree_write(fout,root);
  fclose(fout);
}
return 0;      Γράψε όλα τα στοιχεία του
}                 δένδρου στο αρχείο
                                            69
    Εγγραφή Στοιχείων Δένδρου στο
    Αρχείο
void tree_write(FILE *fp,struct tnode
  *p)   Τα στοιχεία του δένδρου δεν γράφονται
{        ταξινομημένα στο αρχείο επίτηδες
  if (p != NULL) {
     fwrite(p->word,MAXWORD,1,fp);
     fwrite(&p->count,sizeof(int),1,fp);
     tree_write(fp,p->left);
     tree_write(fp,p->right);
  }      Την επόμενη φορά μετρητή του
                                 θα διαβα-
       Γράψε τη λέξη και τονπου υπόλοιπα
          Γράψε αναδρομικά τα
}        στούν (αν ήταν ταξινομημένα) το
         τρέχοντος κόμβου στο αρχείο
               στοιχεία του δένδρου
         δένδρο θα «έγερνε» από τα δεξιά! 70
    Τοποθέτηση Λέξεων που Διαβάζονται
    από το Αρχείο στο Δένδρο
struct tnode *ins_tree(struct tnode *p,char *w,
                                          int c)
{ int cond;
                  Είναι σχεδόν ίδια με την addtree
    if (p == NULL) {         Ο μετρητής δίνεται ως
      p = talloc();
      p->word = strdup(w);
                             παράμετρος
      p->count = c;               Καμία λέξη δεν
      p->left = p->right = NULL;
                                  επαναλαμβάνεται
    }
    else if ((cond = strcmp(w, p->word)) < 0)
      p->left = ins_tree(p->left, w, c);
    else
      p->right = ins_tree(p->right, w, c);
    return p;
}                                               71
Βοηθητικό Πρόγραμμα Εμφάνισης
Περιεχομένων Αρχείου

¡ Θέλουμε ένα βοηθητικό
 πρόγραμμα το οποίο να
 εμφανίζει τα περιεχόμενα ενός
 δυαδικού αρχείου που
 δημιουργήθηκε με το
 προηγούμενο πρόγραμμα
¡ Π.χ.   display out.dat

                                 72
  Βοηθητικό Πρόγραμμα Εμφάνισης
  Περιεχομένων Αρχείου (main)
int main (int argc, char *argv[]) {
   struct tnode *root = NULL;
   char word[MAXWORD];
   FILE *fin,*fout;            Προστασία για
   int count,i;                λάθος αριθμό
                                παραμέτρων
   if (argc < 2) {
     fprintf(stderr,"Program requires 1
filename!\n");
     exit(1);
   }
                                               73
  Βοηθητικό Πρόγραμμα Εμφάνισης
  Περιεχομένων Αρχείου (main)
else {
  if ((fout=fopen(argv[1],"rb"))!=NULL) {
    fread(word,MAXWORD,1,fout);
    fread(&count,sizeof(int),1,fout);
    while (!feof(fout)) {
      root = ins_tree(root, word, count);
      fread(word,MAXWORD,1,fout);
      fread(&count,sizeof(int),1,fout);
    }                   Ανάγνωση εμφάνιση
                      Ταξινομημένηστοιχείων
    fclose(fout);       από αρχείο και
                      στοιχείων δένδρου στην
                        εισαγωγή στο δένδρο
    treeprint(root); οθόνη
  }                                         74
  Βοηθητικό Πρόγραμμα Εμφάνισης
  Περιεχομένων Αρχείου (main)
  else {
    fprintf(stderr,"Cannot open file
%s!\n", argv[1]);
    exit(2);
  }
}
                   Αδυναμία ανοίγματος
return 0;              του αρχείου
}

                                         75
    Παράδειγμα Διαχείρισης Ουράς
    Εκτύπωσης

¡   Θέλουμε να φτιάξουμε ένα πρόγραμμα
    που να «τρέχει» συνέχεια (δαίμονας)
    και όταν υπάρχουν αιτήσεις προς
    εκτύπωση να τις διεκπεραιώνει και να
    περιμένει στη συνέχεια νέες αιτήσεις
¡   Υλοποίηση με ουρά (queue)
¡   Οι αιτήσεις καταγράφονται πάντα σε
    συγκεκριμένο αρχείο

                                         76
Πρόγραμμα που προσθέτει αίτημα για
εκτύπωση αρχείου (print-enqueue.c)
#include <stdio.h>
#define PRINTLOG "pqueue.log"
int main (int argc, char *argv[]) {
   FILE *fout;     • Νέες εγγραφές στο τέλος
   int x;                       Αρχείο αιτημάτων
                   • Αν δεν υπάρχει το αρχείο,
                       δημιουργείται
    fout = fopen(PRINTLOG,"a");
    while (fout == NULL)
        fout = fopen(PRINTLOG,"a");
    for ( x=1; x<argc; x++)
        fprintf(fout,"%s\n",argv[x]);
    fclose(fout);
    return 0;             Εγγραφή άνοιγμα
                     Επιμονή για το όλων των
}                            του αρχείου
                            αιτηθέντων αρχείων   77
 Χρήση προγράμματος

¡ print-enqueue    file1 ... filen

¡ Τα   αρχεία file1... filen θα
 καταγραφούν στο αρχείο
 «pqueue.log» με τη σειρά που
 γράφηκαν ως ορίσματα


                                  78
Πρόγραμμα διαχείρισης αιτημάτων για
εκτυπώσεις αρχείων – Επικεφαλίδα, Δομές
#define PRINTLOG "pqueue.log"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>      • Κόμβος ουράς
                         • Σε κάθε κόμβο
struct node {
                           αποθηκεύεται το
   char *data;
                           όνομα του αρχείου
   struct node *next;      προς εκτύπωση
};
struct queue {
                             Δομή ουράς
   struct node *head;
   struct node *tail;
};                                        79
 Πρόγραμμα διαχείρισης αιτημάτων για
 εκτυπώσεις αρχείων

Αλγόριθμος:
¡ Αρχικοποιείται η ουρά (κενή)

¡ Ανοίγει το αρχείο αιτημάτων για ανάγνωση
¡ Υπάρχει ένας ατέρμονας βρόχος

¡ Διαβάζεται το επόμενο αίτημα για εκτύπωση
  από το αρχείο και το εισάγει στην ουρά
¡ Εξάγεται από την ουρά το πρώτο αίτημα για
  εκτύπωση και τυπώνεται το αρχείο (στην
  οθόνη)
¡ Επανάληψη ανακύκλωσης

                                          80
Πρόγραμμα διαχείρισης αιτημάτων για
εκτυπώσεις αρχείων – Κυρίως Πρόγραμμα
int main (){
 struct queue q;         Αρχικοποίηση ουράς
 FILE *fin;
 char fnameIN[20];
 char fnameOUT[20];        Επιμονή για το
                            άνοιγμα του
                         αρχείου αιτημάτων
  q.head = q.tail = NULL;
  fin = fopen(PRINTLOG , "r");
  while (fin == NULL)
      fin = fopen("pqueue.log", "r");
                                        81
Πρόγραμμα διαχείρισης αιτημάτων για
εκτυπώσεις αρχείων – Κυρίως Πρόγραμμα
 while (1) {                  Ατέρμονας βρόχος
    if (fscanf(fin,"%s\n",fnameIN)!=EOF)
           enqueue(&q,fnameIN);
    if (dequeue(&q,fnameOUT) != -1) {
           printfile(fnameOUT);
    }
                            Διάβασμα ενός
 }
                        ονόματος αρχείου και
 fclose(fin);       Εξαγωγή από την ουρά
                         εισαγωγή στην ουρά
                    του πρώτου αρχείου και
 return 0;                 Αυτές οι εντολές δεν
                         εκτύπωσή του
                             εκτελούνται ποτέ
}
                                                82
    Εισαγωγή στοιχείου στην ουρά
void enqueue(struct queue *q, char *s)
{ struct node *p;

    p = alloc();             Διαφορές με
    p->data = strdup(s);      συνάρτηση
    p->next = NULL;          enqueue που
                            παρουσιάστηκε
    if (q->tail == NULL)
                                 ήδη
          q->head=p;
    else
       q->tail->next = p;
    q->tail=p;
}                                        83
    Εξαγωγή στοιχείου από ουρά
int dequeue(struct queue *q, char *s)
{ struct node *p;
   char *w;
                               Διαφορές με
     p = q->head;           συνάρτηση dequeue
     if (q->head == NULL)   που παρουσιάστηκε
          return -1;               ήδη
      else {
          strcpy(s,q->head->data);
          q->head = q->head->next;
          free(p);
          if (q->head == NULL)
           q->tail = NULL;
          return 0;
      }
}                                           84
    Εκτύπωση περιεχομένων αρχείου
    (στην οθόνη)
void printfile (char *fname)
{ FILE *fin;
   char line[80];

     if ((fin = fopen(fname, "r")) == NULL)
        printf("File %s cannot be
                              opened!\n\n",fname);
     else {
        while (fscanf(fin,"%s\n",line) != EOF)
            printf("%s\n",line);
        printf("\n\n");
        fclose(fin);
     }                      Διάβασμα όλων των
}                        γραμμών του αρχείου και
                        Άνοιγμα αρχείου
                        εκτύπωσή τους στην οθόνη85
    Ταξινόμηση αρχείων με συνένωση
    (mergesort)
¡ Έχουμε 2 αρχεία με γραμμές κειμένου ήδη
  ταξινομημένα
¡ Θέλουμε να τα συνενώσουμε σε ένα τρίτο
  αρχείο το οποίο να είναι επίσης ταξινομημένο
Αλγόριθμος
¡ Διαβάζουμε 1 γραμμή από κάθε αρχείο

¡ Όποια είναι μικρότερη γράφεται στο αρχείο
  εξόδου και ξαναδιαβάζουμε από το αντίστοιχο
  αρχείο
¡ Όταν τελειώσει το ένα από τα 2 αρχεία, οι
  γραμμές του άλλου αντιγράφονται στην έξοδο
                                            86
     Ταξινόμηση αρχείων με συνένωση –
     main (επικεφαλίδες, μεταβλητές)
     #include <stdio.h>
     #include <string.h>

     #define MAXLENGTH 80

       int main(int argc, char *argv[]) {
           FILE *fin1, *fin2, *fout;
Γραμμές
κειμένου   char s1[MAXLENGTH], s2[MAXLENGTH];
           char *c1, *c2;
           int comp;
                                           87
   Ταξινόμηση αρχείων με συνένωση -
   main (άνοιγμα αρχείων)
if (argc < 3) {
  fprintf(stderr,"Usage: mergesort file1 file2
                                         result!\n");
  return 3;   }
if ((fin1 = fopen(argv[1],"r")) == NULL) {
  fprintf(stderr,"Cannot open %s for input!\n",
                                            argv[1]);
  return 1;                               }
if ((fin2 = fopen(argv[2],"r")) == NULL) {
  fprintf(stderr,"Cannot open %s for input!\n",
                                            argv[2]);
  return 1;                               }
if ((fout = fopen(argv[3],"w")) == NULL) {
  fprintf(stderr,"Cannot open %s for output!\n",
                                            argv[3]);
  return 2;                               }      88
          Ταξινόμηση αρχείων με συνένωση -
          main (άνοιγμα αρχείων)
          c1=fgets(s1,MAXLENGTH,fin1);     Διάβασε από
          c2=fgets(s2,MAXLENGTH,fin2);     1 γραμμή
          while ((c1 != NULL) && (c2 != NULL)) {
                comp = strcmp(s1,s2);
Αν η γραμμή
του 1ου
                if (comp < 0) {
αρχείου είναι        fprintf(fout,"%s",s1);
μικρότερη
Αν η γραμμή          c1=fgets(s1,MAXLENGTH,fin1);     }
τύπωσέ την
του 2ου οι 2    else if (comp > 0) {
Αλλιώς
στην έξοδο.
αρχείου είναι
γραμμές              fprintf(fout,"%s",s2);
Διάβασε την
μικρότερη και
είναι ίδιες          c2=fgets(s2,MAXLENGTH,fin2);     }
επόμενητην
τύπωσέ τιςμόνο
τύπωσέ ο
από το 1
στην έξοδο.     else {
και τις 2 στην
αρχείο. την
Διάβασε             fprintf(fout,"%s%s",s1,s2);
έξοδο.
επόμενη τις
Διάβασε ομόνο       c1=fgets(s1,MAXLENGTH,fin1);
από το 2 και
επόμενες            c2=fgets(s2,MAXLENGTH,fin2);      }
αρχείο.2
από τα }
                                                       89
αρχεία.
    Ταξινόμηση αρχείων με συνένωση -
    main
 while (c1 != NULL) {
    fprintf(fout,"%s",s1);
    c1=fgets(s1,MAXLENGTH,fin1); }
 while (c2 != NULL) {
    fprintf(fout,"%s",s2);
    c2=fgets(s2,MAXLENGTH,fin2); }
 fclose(fin1);
 fclose(fin2);
                  Αν δεν έχουν τελειώσει οι
 fclose(fout);    Αν δεν έχουν 2ου αρχείου,
                   γραμμές του τελειώσει οι
 return 0;        αντέγραψέ τις1στην έξοδο.
                   γραμμές του ου αρχείου,
}                   αντέγραψέ τις στην έξοδο.
                                                90

								
To top