Tavoitteena on kerrata ja tutustua lisää tiedostojen käytön periaatteisiin ja perustoimintoihin sekä kerrata hieman listaa.
Erityisesti tarkastellaan siis
poikkeusten käsittelyä ja
listan käyttämistä.
tiedosto = open("diary.txt", "a")
tiedosto.write("Lisäys ohjelmallisesti\n")
tiedosto.close()
"Kun open avaa tiedoston, varaa se sitä varten käyttöjärjestelmältä resurssin, niin sanotun tiedostokahvan (engl. file handle). Vaikka olemme lukeneet kaikki rivit tiedostosta, ei Python tiedä että emme enää tarvitse tiedostoa mihinkään eikä osaa vapauttaa tiedostokahvaa. Jos lukisimme monia tiedostoja näin, pitäisi Python turhaan varattuna tiedostokahvoja ja ne saattaisivat loppua jossain vaiheessa kesken.
On siis parasta vapauttaa kahva ja se tapahtuu metodilla file.close(). Voisimme laittaa kutsun file.close() else-osion loppuun. Tässä esimerkissä tämä tuskin olisi vaarallista, mutta yleensä emme voi olla varmoja, että else-osion koodi ei heitä uusia poikkeuksia, joten on paras laittaa closen kutsu finally-osioon. Siellä tulee kuitenkin tarkistaa, että avaaminen on onnistunut. Tämä selviää tarkistamalla onko muuttuja tiedosto sidottu. "
(Lähde: http://www.cse.tkk.fi/fi/opinnot/CSE-A1121/2015/k04/osa01.html)
Edellisessä koodissa pitäisi siis varautua poikkeuksen käsittelyyn try - except - else - finally -rakenteella seuraavaan tapaan:
try:
tiedosto = open("diary.txt","a")
except OSError:
print("Tiedostoa ei voitu avata.")
else:
tiedosto.write("Lisäys ohjelmallisesti\n")
finally:
if tiedosto:
tiedosto.close()
Oheisesta esimerkistä (joka oli edelliskerralla harjoituksena) puuttuu poikkeuksen käsittely, jotta riveittäin lukemisen periaate olisi helpompi huomata:
tiedosto = open("diary.txt", "r")
for rivi in tiedosto: # luetaan tiedostoa rivi kerrallaan niin kauan kuin rivejä on
rivi = rivi.rstrip() # poistetaan merkkijonon, nimeltään rivi, lopusta rivinvaihtomerkki
print(rivi) # tulostetaan rivi
tiedosto.close()
Tiedostosta ei voi lukea muuta kuin merkkijonotyyppistä tietoa.
Mutta luetun merkkijonon voi
ensin pilkkoa osiin ja
sitten muuntaan kunkin osan haluttuun tietotyyppiin.
Oletetaan, että luvut.txt sisältää ainoastaan kokonaislukuja. Tällöin luvut voidaan laskea yhteen esimerkiksi seuraavasti:
tiedosto = open("luvut.txt", "r")
summa = 0 # alustetaan summa-niminen muuttuja nollaksi
for rivi in tiedosto: # luetaan tiedostoa rivi kerrallaan niin kauan kuin rivejä riittää
luvut = rivi.split() # pilkotaan merkkijono osiin välilyöntien kohdalta tallettaen osat listaan
for luku in luvut:
summa += int(luku) # luku on merkkijono (str), joten se on muutettava kokonaisluvuksi (int)
print(summa)
tiedosto.close()
def printCharacterAndLineCounts(path):
file = None
try:
file = open(path)
except OSError:
print("Could not open {}".format(path))
else:
lineCount = 0
characterCount = 0
for line in file:
lineCount += 1
characterCount += len(line)
print("File {} has {} characters in {} lines".format(path, characterCount, lineCount))
finally:
if file:
file.close()
Tiedostojen peruskäyttöä on vaikea harjoitella pilvessä. Siksi kannattaa aluksi käyttää tietokoneen omaa levymuistia.
Teemu Sirkiän pdf-dokumentti Ohjelmoinnin perusteet Pythonilla.
Tiedostojen käyttöä alkaen sivulta 50.
Etene niin pitkälle kuin ehdit. Kysy rohkeasti apua!
Täydennä seuraava edellisen tiedosto-luennon mukainen harjoitus yksi siten, että tiedoston avaaminen, sen lukeminen ja lopulta sen sulkeminen toteutetaan try - except - else - finally -rakenteessa.
Laadi tarvittaessa tekstityyppinen tiedosto nimeltään kirje.txt. Sisältö on vapaa. Tallenna se samaan kansioon kuin koodisi, jotta ohjelma löytää ko. tiedoston. Tämän pitäisi kuitenkin olla valmiina edellisen kerran jäljiltä.
Voit kopioida koodin tästä tai ottaa esille koodin edelliseltä harjoituskerralta.
tiedosto = open("kirje.txt", "r")
for rivi in tiedosto:
rivi = rivi.rstrip()
print(rivi)
tiedosto.close()
Muistathan, että for-silmukassa tiedostoa luetaan aina rivinvaihtomerkkiin saakka. Tällöin rivi on yhden rivin sisältö ja tyypiltään merkkijono eli str.
Muistathan, että rstrip() -metodi poistaa rivinvaihtomerkin?!
Kopioi oheinen edellisen harjoituskerran harjoituksen kaksi koodi. Täydennä myös siihen try - except - else - finally -rakenne
tiedosto = open("diary.txt", "w")
tiedosto.write("Päiväkirja\n")
tiedosto.write("Rakas päiväkirjani,")
tiedosto.close()
Muuta harjoituksen kaksi koodia siten, että se lisää olemassaolevaan tiedostoon uuden rivin eikä kirjoita aina uutta tiedostoa, kuten parametrin arvolla w tapahtuu. Käytännössä se tarkoittaa tiedoston avaamisessa käytettävän parametrin muuttamista merkinnästä "w" eli write merkinnäksi "a" eli append, mikä suomeksi tarkoittaa 'lisätä loppuun'.
Keksi itse jokin yhden rivin mittainen päiväkirjamerkintä. Tämän saa siis "kovakoodata" eli ohjelma lisää rivin.
Muistathan, että rivinvaihdon voit lisätä "\n" -merkinnällä.
Testaa lukujen lukeminen.
Kirjoita tiedostoon nimeltään luvut.txt seuraavat luvut
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Testaa sitten yllä esitettyä ohjelmaa, joka lukee tiedot ja laskee luvut yhteen.
Lisätehtävä:
Olisi hyvä, jos lisäisit vielä poikkeustenkäsittelyt sekä tiedoston käsittelyyn että merkkijonon käsittelyyn. Mikäli tehtäisiin ammattimaista koodia, se olisi välttämätöntä. Vihjeitä saat mm. Sirkiän opetusmateriaalista sivuilta 56 ja 57.
Kehitä edellistä ohjelmaasi siten, että tiedostosta luetaan desimaalilukuja.
Laadi ohjelma, joka lukee seuraavat tiedot tiedostosta nimeltään kauppalasku.txt ja tulostaa näyttöön ostetut artikkelit ja ostosten yhteissumman.
kahvi 6.56
leipä 2.47
appelsiini 3.15
viikuna 2.15
jogurtti 1.34
Lisätehtävä:
Ohjelma pyöristää loppusumman lähimpään viiteen senttiin.