35 Lugemine failist
Lugemine failist. Tõde ja õigus
Failist lugemist for-tsükli abil oleme varem mitmel korral kasutanud:
fail = open("andmed.txt", encoding="UTF-8") for rida in fail: print("Lugesin sellise rea: " + rida) fail.close()
Pikema teksti lugemise ja analüüsimise näitena võtame käsile Anton Hansen Tammsaare “Tõe ja õiguse” 1. köite. Tegemist on meie rahva ühe tüvitekstiga, mida siin omalaadselt käsitleme. Valdur Mikita on Sirbis kirjutanud: “Rahvas, kelle kõige kuulsam kirjandusteos on viieköiteline sookuivendamise käsiraamat, ei saa olla normaalne – ja ei peagi. Võimalik, et meil on ilmaruumis hoopis üks teine asi ajada.”
Kõigepealt tuleb tekst arvutisse laadida siit. (Kes tahab, võib proovida ka programselt veebist lugemist.)
Järgmine programm loendab, mitu korda on tekstis sõna “tõde” ja mitu korda “õigus”.
Näiteprogramm. Tõed ja õigused
f = open("anton_hansen_tammsaare_tode_ja_oigus_i.txt", encoding='UTF-8') tõde = 0 # loendaja õigus = 0 # loendaja for rida in f: # ridade kaupa sõnad = rida.split() # rea sõnad järjendisse for s in sõnad: # sõnade kaupa if s == "tõde": tõde += 1 if s == "õigus": õigus += 1 print("Failis sõna 'tõde' on", tõde, "korda.") print("Failis sõna 'õigus' on", õigus, "korda.") f.close()
Enesekontroll (1 küsimus)
Sõneotsingu täiendamine
See programm leidis sõnade “tõde” ja “õigus” arvud ainult juhul, kei neile ei järge teisi sümboleid. Kui tahame, et arvesse tuleksid ka need juhud, kus vahetult sõna järel on mingi kindel kirjavahemärk, siis saame kasutada järgmisi võrdlusi. Nii võetakse arvesse need juhud, kus sõna järel on punkt, koma või küsimärk:
if s.strip(".,?") == "tõde": tõde += 1 if s.strip(".,?") == "õigus": õigus += 1
Nüüd vaatame varianti, kus kontrollitakse, kas sõna “tõde” (“õigus”) sisaldub vaadeldavas sõnes:
if "tõde" in s: tõde += 1 if "õigus" in s: õigus += 1
Kui tahame suurte tähtedega variante arvesse võtta, siis saame seda teha nii:
if "tõde" in s.lower(): tõde += 1 if "õigus" in s.lower(): õigus += 1
See lahendus leiab ka nn valepositiivseid vastuseid, näiteks sõna “tõde” sisaldub sõnas “tõdemus”, mis on hoopis erineva tähendusega. Inimkeelsete tekstide põhjalikum automaatne töötlemine on küllaltki keerukas ja siinsetes materjalides me seda ei vaatle.
Veel failist lugemisest. Funktsioon readline
Vaatleme veel mõningaid võimalusi, kuidas failidest andmeid kätte saada. Alustame funktsiooniga readline
, mis võtab failist järgmise rea.
Esialgu teeme käsitsi faili andmed2.txt. Esimesel real on inimese nimi, teisel real vanus (täisarvuna) ning kolmandal real meiliaadress. Fail peab olema plain-text kujul (laiendiga .txt).
Näiteprogramm. Faili lugemine readline abil
f = open("andmed2.txt", encoding="UTF-8") nimi = f.readline() vanus = f.readline() aadress = f.readline() print("Nimi:", nimi) print("Vanus:", vanus, "aastat") print("Aadress:", aadress) f.close()
Käsk open
otsib failisüsteemist üles soovitud faili ja tagastab viite sellele (antud näites salvestasime selle viite muutujasse f
, mis on levinud nimi failide tähistamiseks). Kui tahame avada faili samast kaustast, kus asub programm, siis piisab vaid failinimest koos laiendiga: f = open('andmed2.txt')
. Selleks, et täpitähed õigesti paistaksid, täpsustame kodeeringut argumendiga
.encoding="UTF-8"
Rida
loeb failist ühe rea, milles on meie näites isiku nimi, ning annab selle väärtuse muutujale nimi = f.readline()
nimi
. Järgmisel korral sama käsku kasutades loetakse järgmine rida – meie näites vanus.
Käsk f.close()
paneb faili kinni. Faili sulgemata jätmine võib põhjustada igasuguseid muresid, näiteks võib korduvatel käivitustel olla probleeme juba avatud faili avamisega.
Programmi tööle pannes näeme, et väljundis tekib üleliigseid tühje ridu. Nimelt jäetakse iga rea lõppu alles ka failist pärinev reavahetuse sümbol. Kuna print
lisab omalt poolt veel ühe reavahetuse, siis saamegi neid liigselt. Liigse reavahetuse eemaldamiseks saame kasutada näiteks meetodit strip
, mis ilma argumente määramata eemaldab whitespace-sümbolid (tühikud, reavahetused jms):
nimi = f.readline().strip()
Funktsioonid readlines ja read
Lisaks funktsioonile readline
saab failist info kätte ka funktsiooniga readlines
:
f = open("andmed2.txt", encoding="UTF-8") loetud = f.readlines() f.close() # faili ei lähe enam vaja print(loetud)
Näeme, et muutujas loetud
on list, mille iga element on üks rida näidatud failist.
Veebist lugemisel kasutasime funktsiooni read
. Seda saame kasutada ka failist lugemise korral. Nii saame kogu faili sisu ühe sõnena:
f = open("andmed2.txt", encoding="UTF-8") loetud = f.read() f.close() # faili ei lähe enam vaja print(loetud)
Võime piirata loetavate märkide arvu (näiteks 5 sümbolit):
f = open("andmed2.txt", encoding="UTF-8") loetud = f.read(5) f.close() # faili ei lähe enam vaja print(loetud)
Etteantud märkide arv võib olla ka üks, siis loetakse märke ühekaupa.
Järgmine programm on inspireeritud asjaolust, et SMSi saatmisel on õ-tähte sisaldava sõnumi maksimaalne lubatud pikkus märgatavalt väiksem, sest siis kasutatakse teistsugust kodeeringut. Sageli asendatakse täht õ numbriga 6 (arvatavalt pärineb traditsioon vanade mobiiltelefonide ajast, kus õ-täht üldse puudus). Teeme programmi, mis asendaks kõik õ-tähed sümboliga 6:
Näiteprogramm. Õ asendamine I
f = open("sms.txt", encoding="UTF-8") while True: # lõpmatu tsükkel, kui ei katkestata sümbol = f.read(1) # loetakse üks sümbol if sümbol == "": # kui enam sümboleid pole break # tsükkel katkestatakse if sümbol == "õ": print("6", end = "") # reavahetust ei tule else: print(sümbol, end = "") # reavahetust ei tule f.close() # faili ei lähe enam vaja
Sama ülesande saab lahendada ka kahe for-tsükliga. Välimine tsükkel tegutseb ridade kaupa. Sisemisel võetakse vastavast reast sümboleid:
Näiteprogramm. Õ asendamine II
f = open("sms.txt", encoding="UTF-8") for rida in f: # ridade kaupa for sümbol in rida: # sümbolite kaupa if sümbol == "õ": print("6", end = "") # reavahetust ei tule else: print(sümbol, end = "") # reavahetust ei tule f.close() # faili ei lähe enam vaja
Toome ka kolmanda variandi, kus funktsiooni
kasutades saame faili kogu sisu ühe sõnena käsitleda. Selles sõnes muudame funktsiooni read
replace
abil kõik tähed õ numbriteks 6:
Näiteprogramm. Õ asendamine III
f = open("sms.txt", encoding="UTF-8") failisisu = f.read() asendatudõ = failisisu.replace("õ","6") print(asendatudõ) f.close()