# Αρχεια (I/O)

Ενα απλο παράδειγμα οπου χειριζομαστεε ένα αρχείο και διαβάζουμε τα περιεχομενά του (I/O απο το input/output):

    #Write a file
    out_file = open("test.txt","w")
    out_file.write("This Text is going to out file\nLook at it and see\n")
    out_file.close()

    #Read a file
    in_file = open("test.txt","r")
    text = in_file.read()
    in_file.close()

    print text,

To αποτελεσμα και τα περιεχομενα του αρχειου test.txt είναι:

    This Text is going to out file
    Look at it and see

Παρατηρηστε οτι δημιουργηθηκε ένα αρχειο με το ονομα test.txt στον φακελο (κατάλογο) που έτρεξε το προγραμμά μας. Το `\n` στην συμβολοσειρα λεει στην Python να γραψει μια νέα (newline) στο σημείο οπου το συνανταει.

Μια περιληψη του χειρισμου των αρχείων:

1. Πάρε ένα αντικειμενο - αρχείο με την συνάρτηση `open`.
2. Διάβασε (read) η γραψε (write) στο αρχείο (ανάλογα με τον τροπο που άνοιξε)
3. Κλεισε

Το πρωτο βημα είναι να πάρουμε ενα αρχείο. Το παιρνουμε με την συνάρτηση `open` function. Η συνταξη είναι `file_object = open(filename,mode)` οπου `file_object` είναι η μεταβλητη που θα τοποθετηθει στο αντικείμενο , το `filename` είναι μια συμβολοσειρα με το ονομα του αρχείου, και το `mode` είναι είτε `"r"` για ανάγνωση (read) είτε `"w"` για εγγραφη (write) στο αρχειο. Επειτα καλουνται οι συναρτήσεις αντικειμενων. Οι πιο συνηθεις απο αυτες ειναι η `read` και η `write`. Η συνάρτηση `write` προσθετει μια συμβολοσειρα στο τελος του αρχειου. Η συνάρτηση `read` διαβαζει το επομενο πραγμα μεσα στο αρχείο και το επιστρεφει ως συμβολοσειρα. Αν δεν δωθει παράμετρος, θα επιστραφει ολοκληρο το αρχείο (οπως συμβαινει στο παράδειγμα).

Και τωρα η νεοτερη έκδοση του προγραμματος των τηλεφωνικων αριθμων που ειχαμε γραψει παλιοτερα:

    import string

    true = 1
    false = 0

    def print_numbers(numbers):
        print "Telephone Numbers:"
        for x in numbers.keys():
            print "Name: ",x," \tNumber: ",numbers[x]
        print

    def add_number(numbers,name,number):
        numbers[name] = number

    def lookup_number(numbers,name):
        if numbers.has_key(name):
            return "The number is "+numbers[name]
        else:
            return name+" was not found"

    def remove_number(numbers,name):
        if numbers.has_key(name):
            del numbers[name]
        else:
            print name," was not found"

    def load_numbers(numbers,filename):
        in_file = open(filename,"r")
        while true:
            in_line = in_file.readline()
            if in_line == "":
                break
            in_line = in_line[:-1]
            [name,number] = string.split(in_line,",")
            numbers[name] = number
        in_file.close()

    def save_numbers(numbers,filename):
        out_file = open(filename,"w")
        for x in numbers.keys():
            out_file.write(x+","+numbers[x]+"\n")
        out_file.close()

    def print_menu():
        print '1. Print Phone Numbers'
        print '2. Add a Phone Number'
        print '3. Remove a Phone Number'
        print '4. Lookup a Phone Number'
        print '5. Load numbers'
        print '6. Save numbers'
        print '7. Quit'
        print

    phone_list = {}
    menu_choice = 0
    print_menu()
    while menu_choice != 7:
        menu_choice = input("Type in a number (1-7):")
        if menu_choice == 1:
            print_numbers(phone_list)
        elif menu_choice == 2:
            print "Add Name and Number"
            name = raw_input("Name:")
            phone = raw_input("Number:")
            add_number(phone_list,name,phone)
        elif menu_choice == 3:
            print "Remove Name and Number"
            name = raw_input("Name:")
            remove_number(phone_list,name)
        elif menu_choice == 4:
            print "Lookup Number"
    	name = raw_input("Name:")
            print lookup_number(phone_list,name)
        elif menu_choice == 5:
            filename = raw_input("Filename to load:")
            load_numbers(phone_list,filename)
        elif menu_choice == 6:
            filename = raw_input("Filename to save:")
            save_numbers(phone_list,filename)
        elif menu_choice == 7:
            pass
        else:
            print_menu()
    print "Goodbye"

Βλεπουμε πως μπορουμε να σωσουμε και να φορτωσουμε αρχεία. Να κάποια αποτελέσματα που ειχα τρεχοντάς το δυο φορες:

    > python tele2.py
    1. Print Phone Numbers
    2. Add a Phone Number
    3. Remove a Phone Number
    4. Lookup a Phone Number
    5. Load numbers
    6. Save numbers
    7. Quit

    Type in a number (1-7):2
    Add Name and Number
    Name:Jill
    Number:1234
    Type in a number (1-7):2
    Add Name and Number
    Name:Fred
    Number:4321
    Type in a number (1-7):1
    Telephone Numbers:
    Name:  Jill     Number:  1234
    Name:  Fred     Number:  4321

    Type in a number (1-7):6
    Filename to save:numbers.txt
    Type in a number (1-7):7
    Goodbye

    > python tele2.py
    1. Print Phone Numbers
    2. Add a Phone Number
    3. Remove a Phone Number
    4. Lookup a Phone Number
    5. Load numbers
    6. Save numbers
    7. Quit

    Type in a number (1-7):5
    Filename to load:numbers.txt
    Type in a number (1-7):1
    Telephone Numbers:
    Name:  Jill     Number:  1234
    Name:  Fred     Number:  4321

    Type in a number (1-7):7
    Goodbye

Τα νεα κομμάτια στον κωδικα είναι:

    def load_numbers(numbers,filename):
        in_file = open(filename,"r")
        while 1:
            in_line = in_file.readline()
            if len(in_line) == 0:
                break
            in_line = in_line[:-1]
            [name,number] = string.split(in_line,",")
            numbers[name] = number
        in_file.close()

    def save_numbers(numbers,filename):
        out_file = open(filename,"w")
        for x in numbers.keys():
            out_file.write(x+","+numbers[x]+"\n")
        out_file.close()

Ας εξετάσουμε πρωτα το κομμάτι του κωδικα που σωζει το αρχείο. Αρχικά δημιουργει το αρχείο με την εντολη `open(filename,"w")`. Επειτα συνεχιζει γραφοντας σε μια νεα γραμμη τον κάθε τηλεφωνικο αριθμο με την εντολη `out_file.write(x+","+numbers[x]+"\n")`. Αυτη γραφει μια γραμμή που περιεχει το ονομα, ένα κομμα, τον αριθμο και συνεχιζει με μια νέα γραμμή.

Το κομμάτι που φορτωνει το αρχείο είναι λιγο πιο περιπλοκο. Ξεκιναει παίρνοντας ένα αρχείο. Μετα χρησιμοποιει τον βρογχο `while 1:` για να τον κρατησει μέχρι να συνατησει μια εντολη `break`. Υστερα παιρνει μια νεα γραμμη με το `in_line = in_file.readline()`. Η συνάρτηση `getline` θα επιστρέψει μια αδεια συμβολοσειρα (len(string) == 0) οταν φτασει στο τελος του αρχείου. Η δήλωση `if` ελεγχει για κάτι τετοιο και σπαει (`break`) τον βρογχο του `while` οταν αυτό συμβεί. Βέβαια, αν η συνάρτηση `readline` δεν επεστρεφε την νεα γραμμή στο τέλος καθε γραμμης δεν θα υπηρχε τροπος να καταλαβουμε αν είμαστε σε μια άδεια γραμμη η στο τελος του αρχείου, και έτσι η νεα γραμμη ειναι στα αριστερα αυτου που επιστρεφει η `getline`. Γιαυτο πρεπει να ξεφορτωθουμε την νεα γραμμή. Η εντολη `in_line = in_line[:-1]` το καταφερνει διαγράφοντας τον τελευταιο χαρακτηρα. Η γραμμη `[name,number] = string.split(in_line,",")` χωριζει την γραμμη με βάση το κομμα σε ονομα και σε τηλεφωνο. Η γραμμή αυτη μετα, προστιθεται στο μητρωο `numbers`.

# Ασκησεις

Μετατρέψτε το προγραμμα βαθμολογίας απο το κεφάλαιο 11 έτσι ωστε να χρησιμοποιει αρχεια και να κραταει αρχείο των μαθητων.