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 nimi = f.readline() loeb failist ühe rea, milles on meie näites isiku nimi, ning annab selle väärtuse muutujale 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 read kasutades saame faili kogu sisu ühe sõnena käsitleda. Selles sõnes muudame funktsiooni 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()

Enesekontroll (1 ülesanne)

Litsents

Icon for the Creative Commons Attribution 4.0 International License

Programmeerimine on loodud Eno Tõnisson, Tauno Palts, Merilin Säde, Kaarel Tõnisson jt poolt Creative Commons Attribution 4.0 International License litsentsi alusel, kui pole teisiti märgitud.

Jaga seda raamatut