Etusivu Aloitus Kontrollit Metodit Muuttujat Ohjausrakenteet Silmukat Matematiikka Debuggaus Virheenkäsittely Vuorovaikutus Valikot Tiedostonkäsittely Ikkunat Leikepöytä Drag and Drop Tiedostopäätteet Linkkejä Harjoitukset

Johdanto ja tavoite

Tässä osiossa tutustutaan Visual Basic:in tiedostonkäsittelyyn. Tämän osion jälkeen opiskelija osaa käyttää (lukea ja kirjoittaa) tiedostoja ja käyttää tiedostoja monipuolisesti omissa ohjelmissaan.

Tiedosto

Tiedosto on tietoa, joka sijaitsee esim. kovalevyllä tai korpulla. Tiedostoja ovat esim. kuvatiedostot, äänitiedostot, tekstitiedostot, jne. Tiedostoja on kahdentyyppisiä, tekstitiedostoja (eli niitä voidaan lukea "paljaalla" silmällä) ja binääritiedostoja (joita ei voi oikein paljaalla silmällä lukea).

VB tukee kahdenlaista tiedostonkäsittelyä, "vanhanmallista" ja FSO -malliin pohjautuvaa. Käymme tässä kappaleessa läpi molemmat tavat aloittaen vanhemmasta tavasta.

Vanha malli

Vanha malli on kohtuu helppokäyttöinen, alla on esitetty mallin syntaksi:

Open polkunimi For moodi [Access paasy] [lukitus] As [#]tiedostonumero [Len=tietueenpituus]

Eli aluksi tulee olla OPEN -sana, sen jälkeen polkunimi eli käytännössä tiedosto ja mahdollisesti tiedostopolku (esim. "nimet.txt" tai "c:\temp\nimet.txt"). Moodi on tapa jolla tiedosto avataan, paasy kertoo mitä operaatioita tiedostoon voidaan kohdistaa, lukitus rajaa muiden käyttöoikeutta tiedostoon, tiedostonumero määrittää käytettävän tiedostonumeron ja tietueenpituus tietueen pituuden.

Alla on listattu eri parametrit selityksineen jonka jälkeen esittelemme muutaman mallilauseen:
MoodiSelite
AppendAvataan tiedosto siten, että tietoa lisättäessä se lisätään vanhan tiedon perään.
BinaryAvataan tiedosto binäärimoodiin.
InputAvataan tiedosto luku varten.
OutputAvataan tiedosto kirjoittamista varten, mahdollinen vanha tieto ylikirjoitetaan.
RandomRandom access eli tiedostoa voidaan "käpistellä" miten sattuu.

PääsySelite
ReadLuku
WriteKirjoitus
Read WriteLuku ja kirjoitus

Tiedoston luku ja kirjoitus on lukittu muilta prosesseilta
LukitusSelite
SharedMuutkin prosessit voivat käyttää tiedostoa
Lock ReadTiedoston luku on lukittu muilta prosesseilta
Lock WriteTiedoston kirjoitus on lukittu muilta prosesseilta
Lock Read Write

OminaisuusSelite
TiedostonumeroJokaisella avattavalla tiedostolla tulee olla oma numeronsa väliltä 1 - 511.
Huom! Seuraavan vapaan tiedostonumeron saat selville FreeFile -komennolla!
TietueenpituusRandom -moodissa avatuille tiedostoille tämä arvo on tietuun pituus, muille tämä on puskuroitavien merkkien määrä.

Tekstitiedoston käsittely

Ensimmäisessä esimerkissämme avaaamme C -aseman Temp -kansioon tiedoston kirjoitusta varten, tiedoston nimi on nimet.txt:
Open "c:\temp\nimet.txt" For Output As #1
Close #1
Tästä esimerkistä ei ole vielä paljoa hyötyä koska emme ole saaneet kirjoitettua tiedostoon mitään tietoa. Kun saimme tiedoston auki, suljimme sen tietysti lopuksi.

Seuraavassa esimerkissä jatkamme edellistä harjoitusta siten, että kirjoitamme avattuun tiedostoon muutaman rivin tekstiä (nimiä). Tiedostoon kirjoittamisessa ja tiedoston lukuun on käytettävissä "hienostunut" tapa ja "raaka" tapa. Hienostuneessa tavassa käytämme Print -komentoa tiedon lisäyksessä ja Line Input -metodia tiedon luvussa. Raa'assa tavassa vastaavat komennot ovat Write ja Input. Em. komennot vaativat tiedostonumeron, johon kirjoitus kohdistuu.

Open "c:\temp\nimet.txt" For Output As #1
Print #1, "Teppo Testaaja"
Print #1, "Jussi Julma"
Print #1, "Liisa Lipsukka"
Close #1
Käydäänpä esimerkki läpi rivi riviltä. Ensimmäisellä rivillä avaamme tiedoston kirjoitusta varten, seuraavat kolme riviä käytetään tiedon kirjoittamiseen, jokaiselle riville tulee yksi nimi. Lopuksi suljemme tiedoston. Huomaa, että jokainen komento vaatii parametrikseen tiedostonumeron.

Tiedoston luonti
Kuvassa olemme avanneet Muistioon juuri luomamme tiedoston.

Seuraavaksi opettelemme lukemaan juuri luomaamme tiedostoa (huomaa, että käsittelemme nyt siis tekstitiedostoja):

Dim Tieto As String

Open "c:\temp\nimet.txt" For Input As #1
Line Input #1, Tieto
MsgBox Tieto
Line Input #1, Tieto
MsgBox Tieto
Line Input #1, Tieto
MsgBox Tieto
Close #1
Esimerkissä avaamme saman tiedoston lukua varten. Tiedoston yksi (ensimmäinen) rivi luetaan Line Input -käskyllä. Tämä käsky vaatii kaksi parametria, tiedostonumeron (eli mistä tiedostosta rivi luetaan) ja muuttujan, johon luetun rivin tieto laitetaan. Rivin luvun jälkeen tulostetaan saatu tieto viestilaatikolla. Koska tiedämme, että meillä on juuri edellä luodussa tiedostossa kolme riviä (kolme nimeä), voimme lukea kolme kertaa. Jos yritämme lukea enemmän, syntyy siitä virhe.

Kuten ehkä huomasit, edellä esitetty tiedostonlukutapa ei ole hyvä etenkin silloin kun emme tiedä luettavan tiedoston pituutta. Kirjoitamme edellisen esimerkin uusiksi:

Dim Tieto As String

Open "c:\temp\nimet.txt" For Input As #1

' Ollaan silmukassa kunnes tulee tieto
' tiedoston loppumisesta
Do Until EOF(1)
	Line Input #1, Tieto
	MsgBox Tieto
Loop

Close #1
Esimerkissämme on kaksi uutta asiaa, ensinnäkin käytämme EOF -käskyä joka palauttaa arvon True jos olemme tiedoston lopussa, muussa tapauksessa palautetaan False -arvo. EOF -käsky tarvitsee parametrikseen tiedoston numeron. Nyt esimerkkiohjelmamme toimii vaikka tiedosto olisi tyhjä (paitsi jos tiedostoa ei ole) tai olet lisännyt tai poistanut tiedostosta rivejä.

Huomaa, että voit kirjoittaa tekstitiedostoon myös Write -komennolla. Alla on esitetty sama esimerkki Write- ja Input -komennoilla toteutettuna:

Open "c:\temp\nimet.txt" For Output As #1
Write #1, "Teppo Testaaja"
Write #1, "Jussi Julma"
Write #1, "Liisa Lipsukka"
Close #1

Dim Tieto As String

Open "c:\temp\nimet.txt" For Input As #1

' Ollaan silmukassa kunnes tulee tieto
' tiedoston loppumisesta
Do Until EOF(1)
	Input #1, Tieto
	MsgBox Tieto
Loop

Close #1
Huomaat eron aikaisempaan kun avaat tiedoston esim. Muistio:lla ja tutkit miten ohjelma on kirjoittanut nimet, nimien ympärillä on heittomerkit! Eli Write -kirjoittaa tiedot "raakana".

Binaari- ja Random -tiedostoje käsittely

Binääri- ja Random (Access) -tiedostojen käsittely eroaa "normaalista" mm. siten, että sinun tulee käyttää) Put ja Get -lauseita tiedon tallentamiseen ja lukemiseen. Toinen merkittävä ero on siinä, että tietojen käsittely on hankalampaa, sinun tulee tietää tiedon pituus osataksesi hakea sen tiedostosta. Seuraavassa esimerkissä on esitelty yksi tapa tallentaa tietoa (nimiä) tiedostoon ja lukea ne pois:
Dim Tieto As String * 20

Open "c:\temp\binaari.dat" For Binary Access Write As #1
Tieto = "Teppo Testaaja"
Put #1, , Tieto
Tieto = "Jouko Julma"
Put #1, , Tieto
Close #1

Tieto = ""

Open "c:\temp\binaari.dat" For Binary Access Read As #1 Len = Len(Tieto)

' Ollaan silmukassa kunnes tulee tieto
' tiedoston loppumisesta
Do Until EOF(1)
	Get #1, , Tieto
	MsgBox Tieto
Loop

Close #1
Alussa määrittelemme muuttujan, johon tieto tallennetaan. Huomaa, että String -määritteen perässä on * 20 -merkintä mikä tarkoittaa sitä, että tiedon pituus on aina 20 merkkiä riippumatta onko nimi sitä lyhyempi (täytetään loppu tyhjällä) tai pitempi (katkaistaan loput). Avaamme tiedoston binäärimoodin lukua varten ja kirjoitamme tiedostoon kaksi nimeä, "Teppo Testaaja" ja "Jouko Julma". Suljemme tiedoston, nollaamme muuttujan ja avaamme saman tiedoston lukua varten, nyt meidän tulee määritellä tietueen pituus (eli käytännössä tietue on nyt 20 merkkiä eli 20 tavua pitkä String -tyyppinen tieto). Käymme silmukassa tiedoston läpi lukien tietue kerrallaan tietoa ja tulotamme tiedon viestilaatikolla. Huomaa, että vaikka meillä on kaksi riviä tietoa, tulostuu kolme viestilaatikkoa, kolmas tietue on tyhjä eli tiedosto loppuu siihen.

Huomaamme nyt, että jos haluamme tallentaa enemmän tietoa, meidän on kaikista helpoin tehdä oma muuttuja eli käyttää tyyppimäärittelyä. Seuraavassa esimerkissä määrittelemme uuden tyypin nimeltä Tietue:

Private Type Tietue
    Nimi As String * 20
    Osoite As String * 30
    Ika As Integer
End Type
Kun olemme saaneet määriteltyä tietueemme, on hyvä opetella käyttämään sitä:
Dim Nimi1 As Tietue
Dim Nimi2 As Tietue
Dim Vastaus As Tietue

Nimi1.Nimi = "Jouko Julma"
Nimi1.Osoite = "Luolamiehenkatu 2"
Nimi1.Ika = 45

Nimi2.Nimi = "Teppo Testaaja"
Nimi2.Osoite = "Krässikuja 4"
Nimi2.Ika = 26

Open "c:\temp\random.dat" For Random Access Write As #1 Len = Len(Vastaus)
Put #1, , Nimi1
Put #1, , Nimi2
Close #1

Open "c:\temp\random.dat" For Random Access Read As #1 Len = Len(Vastaus)

' Ollaan silmukassa kunnes tulee tieto
' tiedoston loppumisesta
Do Until EOF(1)
	Get #1, , Vastaus
	MsgBox Vastaus.Nimi & " " & Vastaus.Osoite & " " & Vastaus.Ika
Loop

Close #1
Aluksi määrittelemme kolme Tietue -tyyppistä muuttujaa, joista kahteen (Nimi1 ja Nimi2) syötämme arvoja. Sitten avaamme Random (Access) -tiedoston (toki voisi käyttää binääritiedostoakin) kirjoitusta varten ja huomaa Len -sana! Len -sanan päässä on Len -lause, joka palauttaa tietueen pituuden. Kirjoitamme tiedot ja suljemme tiedoston.

Jos tutkit nyt tiedostoa (tai edellistä binääritiedostoakin), huomaat, että sisältö on "ökkömökköä" eli sitä ei voi muokata "käsin". Lähdemme nyt lukemaan tiedostoa avaamalla sen Random -moodissa lukua varten ja taas täytyy määritellä tietueen pituus, muutoin luku (ja vastaavasti kirjoitus) epäonnistuu. Luemme tietueita kunnes olemme tiedoston lopussa ja tulostamme kunkin tietueen tiedot.

Käytännössä siis binääri ja Random -tavoilla on vain pienen pieniä eroja. Lisätietoja eroista löydät mm. VB:n ohjeista.

Tehtävä 22

FSO -malli