Datan tallentaminen, lataaminen ja siirtäminen



Samankaltaiset tiedostot
Ohjelmoinnin perusteet Y Python

Maastotietokannan torrent-jakelun shapefile-tiedostojen purkaminen zip-arkistoista Windows-komentojonoilla

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

Jypelin käyttöohjeet» Ruutukentän luominen

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Kehitysympäristö LUKU. Developer Studio kehitysympäristön alkeet. Liikkuminen projektin työtilassa ja sen eri näkymissä

Written by Administrator Monday, 05 September :14 - Last Updated Thursday, 23 February :36

EASY Tiedostopalvelin - mobiilin käyttöopas

MDI-sovellusten kehittäminen

Muuttujien määrittely

BlueJ ohjelman pitäisi löytyä Development valikon alta mikroluokkien koneista. Muissa koneissa BlueJ voi löytyä esim. omana ikonina työpöydältä

Tiedostot. Tiedostot. Tiedostot. Tiedostot. Tiedostot. Tiedostot

Tik Tietojenkäsittelyopin ohjelmatyö Tietotekniikan osasto Teknillinen korkeakoulu KÄYTTÖOHJE. LiKe Liiketoiminnan kehityksen tukiprojekti

Osoitin ja viittaus C++:ssa

Tulosta yrityksesi tuloslaskelma ja tase myöhempää tarkastusta varten. Ota varmuuskopio tilanteesta ennen tilimuunnosta.

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Hiirisanomiin vastaaminen

MPCC-työkalua voidaan käyttää yhden laitteen valvontaan ja yhden tai useamman laitteen konfigurointiin (Modbus broadcast, osoite 0).

Ohjelmoinnin perusteet Y Python

WCONDES OHJEET ITÄRASTEILLE (tehty Condes versiolle 8)

Taulukot. Jukka Harju, Jukka Juslin

Sähköposti ja uutisryhmät

Pong-peli, vaihe Aliohjelman tekeminen. Muilla kielillä: English Suomi. Tämä on Pong-pelin tutoriaalin osa 3/7. Tämän vaiheen aikana

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

C-kielessä taulukko on joukko peräkkäisiä muistipaikkoja, jotka kaikki pystyvät tallettamaan samaa tyyppiä olevaa tietoa.

Tietojen tallentaminen

Olio-ohjelmointi Javalla

Mikäli olet saanut e-kirjan latauslinkin sähköpostilla, seuraa näitä ohjeita e-kirjan lataamisessa.

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

Ohjeet e kirjan ostajalle

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

TEHTÄVÄ 1.1 RATKAISUOHJEET

KUVAN TUOMINEN, MUOKKAAMINEN, KOON MUUTTAMINEN JA TALLENTAMINEN PAINTISSA

OpenOffice.org Base 3.1.0

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b

Pedacode Pikaopas. Java-kehitysympäristön pystyttäminen

Vaatimusten versiointi DOORSissa

Ohjelmoinnin perusteet Y Python

Merkkijono määritellään kuten muutkin taulukot, mutta tilaa on varattava yksi ylimääräinen paikka lopetusmerkille:

Google-dokumentit. Opetusteknologiakeskus Mediamylly

Dokumentit, näkymät ja kehykset

Pedanet oppilaan ohje Aleksanteri Kenan koulu Eija Arvola

Ohjelmoinnin perusteet Y Python


Visual C++ -ohjelman tekeminen ja suunnittelu

1. Adobe Digital Editions ohjelman käyttöönotto

Ohjelmoinnin perusteet Y Python

Usean näkymän luominen

Valintanauhan komennot Valintanauhan kussakin välilehdessä on ryhmiä ja kussakin ryhmässä on toisiinsa liittyviä komentoja.

MOODLE TUTUKSI. Pirkko Vänttilä Oulun aikuiskoulutuskeskus

Ohjelmoinnin perusteet Y Python

ETAPPI ry JOOMLA 2.5 Mediapaja. Artikkeleiden hallinta ja julkaisu

RockID-varastonhallintajärjestelmän käyttöohje. v. 1.0

ALVin käyttöohjeet. Kuvaus, rajaus ja tallennus puhelimella ALVin -mobiilisovelluksen avulla dokumentit kuvataan, rajataan ja tallennetaan palveluun.

15. Ohjelmoinnin tekniikkaa 15.1

SSH Secure Shell & SSH File Transfer

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

EMVHost Online SUBJECT: EMVHOST ONLINE CLIENT - AUTOMAATTISIIRROT COMPANY: EMVHost Online Client sovelluksen käyttöohje AUTHOR: DATE:

Kaakkois-Suomen Ammattikorkeakoulu Oy Mikkelin Ammattikorkeakoulu Oy Kymenlaakson Ammattikorkeakoulu Oy

Tiedostojen lataaminen netistä ja asentaminen

EASY Tiedostopalvelin - mobiilin käyttöopas

Web Services tietokantaohjelmoinnin perusteet

SoleMOVE lähtevän harjoittelijan ohje

WCONDES OHJEET ITÄRASTEILLE (tehty Condes versiolle 8)

Osa III. Olioiden luominen vapaalle muistialueelle

Outlook Web App ver 1.2

CISS Base Excel raporttien määritys Käyttäjän käsikirja. CISS Base Käyttäjän Käsikirja Econocap Engineering Oy 1

Java-kielen perusteet

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

Muistitikun liittäminen tietokoneeseen

BLOGGER. ohjeita blogin pitämiseen Googlen Bloggerilla

Sen jälkeen Microsoft Office ja sen alta löytyy ohjelmat. Ensin käynnistä-valikosta kaikki ohjelmat

Luku 7 Uusien Mallien Tiedostot

FOTONETTI BOOK CREATOR

ELOKUVAKASVATUS SODANKYLÄSSÄ VIDEON SIIRTÄMINEN DVD-LEVYLLE

Sonera Viestintäpalvelu VIP VIP Laajennettu raportointi Ohje

Ohjelmoinnin peruskurssi Y1

Osa. Listaus 2.1. HELLO.CPP esittelee C++ -ohjelman osat. 14: #include <iostream.h> 15: 16: int main() 17: {

Ohjelmoinnin perusteet Y Python

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

7. Näytölle tulostaminen 7.1

Ohjelmoinnin perusteet Y Python

Valitse aineisto otsikoineen maalaamalla se hiirella ja kopioimalla (Esim. ctrl-c). Vaihtoehtoisesti, Lataa CSV-tiedosto

2. Lisää Java-ohjelmoinnin alkeita. Muuttuja ja viittausmuuttuja (1/4) Muuttuja ja viittausmuuttuja (2/4)

Oppilaan pikaopas. Project 2013 käyttöliittymä ja näkymät

Condes. Quick Start opas. Suunnistuksen ratamestariohjelmisto. Versio 7. Quick Start - opas Condes 7. olfellows 1.

ActiveX-kontrollien käyttö

ohjeita kirjautumiseen ja käyttöön

Tilastolliset ohjelmistot A. Pinja Pikkuhookana

ARVI-järjestelmän ohje arvioinnin syöttäjälle

Sisältö. 2. Taulukot. Yleistä. Yleistä

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä

2013 -merkistä tunnistat uudet ominaisuudet

DumpDbox-ohjelmiston asennus- ja käyttöohjeet Sisällys

KESKUSTANUORTEN NETTISIVUT- OHJEITA PIIRIYLLÄPITÄJÄLLE 1. KIRJAUTUMINEN

9. Periytyminen Javassa 9.1

Transkriptio:

Datan tallentaminen, lataaminen ja siirtäminen OSA VI 547 LUKU 23 23 LUKU Datan tallentaminen, lataaminen ja siirtäminen Dokumentin tietojen tallentaminen ja lataaminen Tiedostojen luominen, lukeminen ja kirjoittaminen Tiedon siirtäminen leikepöydälle ja leikepöydältä

548 Tiedostojen käsittely valintaikkunasovelluksissa Valintaikkunasovelluksen eivät tavallisesti tarvitse serialisoinnin käyttöä - tavallisesti riittää CFilen tukema suora tiedostojen käsittely (josta lisää myöhemmin tässä luvussa). Valintaikkunsovellukset voivat kuitenkin käyttää serialisointia CArchive-luokan kautta. Tätä varten valintaikkunaan joudutaan toteuttamaan oma käyttöliittymä serialisoinnin aloittamista varten. Sovelluksen tietojen ulkoistaminen Datan tallentaminen, lataaminen ja siirtäminen Serialisoinnin käyttö Serialisointi on tekniikka, jolla sovelluksen data saadaan peräkkäiseksi luetteloksi dataelementtejä, sekä saadaan ne tallennettua levylle tai siirrettyä toiseen ohjelmaan. Ohjelman ladatessa uudelleen serialisoidun tiedon tai hyväksyessä toiselta ohjelmalta tulevan tiedon, se voi lukea nämä dataelementit peräkkäin ja muodostaa niistä rakenteisia ja vuorovaikutteisia muistiolioita. SDI- ja MDI-sovellusrungoissa saadaan käyttöön serialisointi ja tiedostonkäsittely joudut ainoastaan tekemään sovelluksesi datan itsensä serialisoivaksi sovellusrungon sitä pyytäessä. Tiedostoja käsittelevän SDI-sovellusrungon luominen Luodaksesi tavallisen dataolioita luovan, käyttävän ja CDocumentluokasta peritystä luokasta serialisoivan SDI-sovelluksen voit käyttää tuttua AppWizardin New Project toimintoa. Joudut huomioimaan serialisoinnin uutta projektia luotaessa ainoastaan dokumenttimallin tekstiasetusten kohdalla (Document Template String). Nämä tekstiasetukset saadaan tehtyä MFC AppWizardin vaiheessa Step 4 napauttamalla Advanced-painiketta. Tällöin saadaan esiin Advanced Options ikkuna (kuva 23.1), josta voit asettaa dokumenttimallikohtaiset tekstitiedot: File extension voit määrittää tiedostotunnisteen muuttamalla File extension ruudun sisältöä. Tähän kelpaavat kaikki aakkosnumeeriset merkit. Sovellusrungon tallettaessa dokumenttisi tiedostoksi käytetään sen nimessä tätä tunnistetta. Sovellusrungon tiedostosuodattimet Advanced Options -valintaikkunan valinnat tallennetaan IDR_MAINFRAMEmerkkijonoresurssiin. Voit muuttaa näitä asetuksia projektin luomisen jälkeen muokkaamalla ResourceView-sivulta löytyvää IDR_MAINFRAME-merkkijonoresurssia (String Table). File type ID Voit määrittää järjestelmärekisteriä varten dokumenttityypin, jotta sovellukset voisivat liittää sovelluksesi tämän tyyppisiin tiedostoihin. Tavallisesti tähän jätetään sovelluksen nimeen perustuva oletusarvo. Näin sovelluksesi saadaan käynnistymään automaattisesti ja lataamaan tiedosto, jota kaksoisnapautetaan työpöydällä tai Resurssienhallinnassa. Filter name Voit määrittää tiedostotunnisteellesi oletussuotimen esimerkiksi tiedoston avaamisikkunassa käytettäväksi.

Datan tallentaminen, lataaminen ja siirtäminen File type name Tämä on File type ID tunnisteeseen liittyvä selkokielisempi nimi käytettäväksi muiden sovelluksien kuvatessa dokumenttityyppiäsi. Näitä rekisteröityjä nimiä saat esiin työpöydän pikavalikon Uusi-valikosta (New). Tätä rekisteröintiä käsitellään myöhemmin tässä luvussa. File new name Voit määrittää oletusnimen tiedostoille, jotka tallennetaan nimettöminä. Tee siis serialisoinnin havainnollistamista varten AppWizardilla uusi SDI-projekti nimeltään Persist. Projektia luodessa hyväksy AppWizardin oletusasetukset vaiheissa Step 1 Step 3 Next-painiketta napauttamalla. Napauta vaiheessa Step 4 Advanced-painiketta, jolloin saat esiin Advanced Options ikkunan. Aseta Persist-esimerkin tiedostotunnisteeksi (File extension) blb, jolloin sovelluksen luomista tiedostoista tulee.blb-päätteisiä (kuva 23.1). OSA VI LUKU 23 549 KUVA 23.1 Tiedostotyyppisuotimen asettaminen Advanced Options ikkunassa. KATSO MYÖS Lisätietoja SDI-sovellusten luomisesta luvusta 12. Merkkijonoresurssien muokkaaminen luvussa 2. Serialisoitavien dataolioiden luominen Kaikilla MFC:n CObject-luokasta periytyvillä luokilla on Serialize()-virtuaalifunktio, jonka voit korvata sovelluksesi luokassa

550 Siirrä tietoa verkon kautta CArchiven avulla Voit käyttää CArchive-luokkaa yhdessä CSocket- ja CSocketFile-luokkien kanssa. Näin voit siirtää tietoa lähiverkon koneesta toiseen tai jopa Internetissä. Serialisointiskeemat ja tietokantaskeemat Samasta käsitteestä huolimatta serialisointiskeemat ovat hyvin erilaisia tietokantaskeemoista. Tietokantaskeemoissa on tieto tietokannan taulujen kentistä ja serialisointiskeemoissa ainoastaan luokan tyypistä ja versiosta. Sovelluksen tietojen ulkoistaminen Datan tallentaminen, lataaminen ja siirtäminen ja pääset tallettamaan olion jäsenmuuttujia levytiedostoon. Kun käyttäjä valitsee SDI- tai MDI-sovelluksessa File Save tai File Open (Tiedosto Tallenna, Tiedosto Avaa), sovellusrunko kutsuu automaattisesti dokumentin Serialize()-funktiota dokumentin dataolioiden tallentamista tai lataamista varten. MFC:n CArchive-luokka vastaa CObjectista johdettujen olioiden serialisoimisesta CArchive-luokkaan upotettuun tiedostojäsenmuuttujaan (tai muuttujasta). Sovellusrunko muodostaa CArchive-olion ja liittää sen tiedostoon, jota käyttäjä on lataamassa tai tallentamassa. Voit korvata dokumenttiluokkasi (joka on johdettu CObjectista) Serialize()-funktion. Tallennettaessa tai ladattaessa dokumenttisi korvatulle Serialize()- funktiolle välitetään parametri ar, joka on sovellusrungon luoma CArchive-olio. Tähän CArchive-olioon sisältyy upotettu tiedostojäsenmuuttuja, joka on liitetty tallennettavaan tai ladattavaan levytiedostoon. Dokumenttiluokkasi Serialize()-funktiosta joudut kutsumaan sovelluksesi kaikkien olioiden Serialize()-funktioita ja välittämään sille CArchive-olion (ar), jonka dokumenttisi Serialize() sai sovellusrungolta. Kun dokumentin tietoja tallennetaan, kunkin serialisoitavan olion data luetaan ja se tallennetaan CArchive-olioon liittyvään tiedostoon. Kun dokumentin tietoja ladataan, data luetaan CArchive-olioon liittyvästä levytiedostosta ja asetetaan takaisin dataolioihin kutsumalla olioiden omia Serialize()-funktioita. Serialisoinnin luomaa levytiedostoa kutsutaan serialisoiduksi arkistotiedostoksi (serialized archive file) ja siihen on tallennettu jokaisen sovelluksen olion data sekä olion tyyppi ja versiotiedot. Versionumeron avulla voit pitää yllä tietoa olion mahdollisesti muuttuvasta rakenteesta sovelluksen kehittyessä. Versio- ja tyyppitietoja nimitetään usein skeemaksi (schema). Voit johtaa sovelluksesi luokat CObjectista ja käyttää serialisointitoimintoja lisäämällä luokan määrittelyyn DECLARE_SERIAL-makron ja vastaavan IMPLEMENT_SERIAL-makron sen toteutuskoodiin. Nämä makrot korvaavat tavalliset CObjectista johdetuissa luokissa käytetyt DECLARE_DYNCREATE- ja IMPLEMENT_DYNCREATE-makrot lisäten serialisointia nopeuttavaa koodia.

Datan tallentaminen, lataaminen ja siirtäminen Serialisoitavan luokan määrittely Mikäli sovelluksesi tarvitsee erityisiä dataolioita, joudut luomaan omat sovelluskohtaiset luokkasi tuon datan kuvaamiseen ja käsittelyyn. Tämän jälkeen voit lisätä uuden luokkasi määrittelyyn serialisointimakrot ja toiminnot kunkin olion datan tallentamiseksi ja lataamiseksi. Voit luoda uuden header-tiedoston (.h) ja toteutustiedoston (.cpp) luokan määrittelylle ja toteutuskoodille. OSA VI LUKU 23 551 Uuden header-tiedoston luominen luokan määrittelylle 1. Valitse Developer Studion File-valikosta New aivan kuten uutta projektia luotaessa. 2. Valitse New-valintaikkunan Files-välilehdellä C/C++ Header File uuden tiedoston luomiseksi. 3. Anna uudelle header-tiedostolle nimi File Name ruutuun (tässä blob.h). 4. Jos Add to Project valinta on asetettu (kuten oletuksena on), uusi tyhjä header-tiedosto lisätään projektiin automaattisesti ja se näytetään editorin ikkunassa. Varmista siis, että valinta on rastitettu. 5. Lisää uusi header-tiedosto projektiin ja aloita sen muokkaus valitsemalla OK. Listauksessa 23.1 esitetään yksinkertaisen serialisoitavan olion määrittely. Tämä luokka on normaali CObjectista johdettu luokka, johon DECLARE_SERIAL-makro lisää MFC:n serialisoinnin vaatiman osan. LISTAUS 23.1 LST23_1.CPP blob.h, Blob-dataolion luokkamäärittely 1 // ** Ensure the class isn't declared twice 2 #ifndef _BLOB_H 3 #define _BLOB_H 4 5 // ** Derive a CBlob class from CObject 6 class CBlob : public CObject 7 { 8 // ** Include the Serialization functions 9 DECLARE_SERIAL(CBlob); 1 10 11 public: 12 1 DECLARE_SERIAL-makro tarjoaa avattuna kaiken sovellusrungon serialisoinnille tarvittavan tuen.

552 2 Yhden Blob-olion (täplän) piirtämiseen tarvittavat attribuutit. Sovelluksen tietojen ulkoistaminen Datan tallentaminen, lataaminen ja siirtäminen 13 // ** Declare two constructors 14 CBlob(); 15 CBlob(CPoint ptposition); 16 17 // ** Declare a drawing function 18 void Draw(CDC* pdc); 19 20 // ** Declare the attributes 21 CPoint m_ptposition; 2 22 COLORREF m_crcolor; 23 int m_nsize; 24 unsigned m_nshape; 25 }; 26 27 #endif // _BLOB_H Riviltä 6 nähdään, että uusi CBlob-luokka on johdettu CObjectkantaluokasta. Kaikki MFC-yhteensopivat luokat kannattaa johtaa CObjectista, koska CObject tarjoaa yleisenä kantaluokkana muitakin hyödyllisiä MFC-ominaisuuksia, kuten ajonaikaiset luokkatiedot. Näiden tietojen avulla MFC voi päätellä, mihin luokkaan olio kuuluu. Nämä tiedot on tallennettu olion datan yhteyteen, joten tietoja ladattaessa voidaan luoda myös oikeanlaiset oliot. Rivin 9 DECLARE_SERIAL-makro lisää serialisoinnin toiminnan vaatiman koodin. Riveillä 14 ja 15 on määritelty kaksi muodostinta. Rivin 14 versio toimii ilman parametrejä ja sitä sovellusrunko käyttää olioiden luomiseen lennossa ladattaessa tietoja levyltä. Rivin 15 versiolla luodaan olio ja sen koordinaattijäsen alustetaan automaattisesti CPoint-parametristä. Tämä helpottaa olioiden luomista hiiren napautuksen perusteella, kuten tulet myöhemmin huomaamaan. Rivillä 18 määritellään Draw()-funktio, jonka toteutuskoodi löytyy.cpp-tiedostosta. Rivien 21 ja 23 muuttujat joudutaan serialisoimaan oliota ladattaessa tai tallennettaessa. Serialisoitavan luokan toteutus Määriteltyäsi uuden luokan joudut kirjoittamaan vastaavan toteutuskoodin luokan määrittelyssä esitellyn datan muodostamiseen (alustamiseen) ja muokkaamiseen.

Datan tallentaminen, lataaminen ja siirtäminen OSA VI LUKU 23 553 Uuden.cpp-tiedoston luominen luokan toteuttamiseen 1. Valitse Developer Studion File-valikosta New aivan kuten uutta projektia luotaessa. 2. Valitse New-valintaikkunan Files-välilehdellä C/C++ Implementation File uuden tiedoston luomiseksi. 3. Anna uudelle toteutustiedostolle nimi File Name ruutuun (tässä blob.cpp). 4. Jos Add to Project valinta on asetettu (kuten oletuksena on) uusi tyhjä toteutus-tiedosto lisätään projektiin automaattisesti ja se näytetään editorin ikkunassa. Varmista siis, että valinta on rastitettu. 5. Lisää uusi toteutustiedosto projektiin ja aloita sen muokkaus valitsemalla OK. Serialisoitavalla luokalla on oltava yleinen - eli parametriton muodostin. Tällä muodostimella oliot luodaan levytiedostosta serialisoitaessa. MFC sovellusrunko voi tällöin kutsua kaiken tyyppisten olioiden yleistä muodostinta niiden luomiseksi ladattaessa tietoja tiedostosta. Yleisellä muodostimella sovellusrunko voi luoda minkä tahansa serialisoitavan luokan ilmentymän ja luottaa sitten sovelluksen omien Serialize()-funktioiden toteutusten alustavan uuden olion jäsenmuuttujien arvot. Voit lisäksi toteuttaa muita muodostimia, joilla voit luoda olioita halutuin alkutiedoin. Jokaisen serialisoitavan olion toteutuskoodissasi tulee olla myös IMPLEMENT_SERIAL-makro. Tämä makro tarvitsee kolme parametriä. Ensimmäinen on itse luokan nimi, toinen sen kantaluokka ja kolmas (wschema) on versionumeroa kuvaava UINT-arvo. Jos lisäät luokkaasi uusia jäsenmuuttujia ja haluat serialisoida ne, voit kasvattaa versionumeroa ja valinnaisesti jopa tarkistaa sen, jos haluat säilyttää yhteensopivuuden vanhempiin serialisointitiedostoihin. CBlob-esimerkkiluokan toteutus on esitetty listauksessa 23.2. Esimerkkitoteutus esittää IMPLEMENT_SERIAL-makron ja useita muodostimia sekä koodin, jolla olio saadaan piirtämään itsensä. Työskentely Visual Source Safen kanssa Jos käytetät integroitua versionhallintajärjestelmää, kuten Visual Source Safea, sinulta kysytään, haluatko lisätä uuden lähdekooditiedoston Source Safe -projektiin (mikä kannattaa tehdä). Versionhallintaohjelmiston avulla voidaan seurata eri ohjelmaversioita ja muutoksia lähdekooditiedostoissa, jolloin aiempaan versioon palaaminen tulee mahdolliseksi. Tämä on erityisen hyödyllistä, kun samassa projektissa työskentelee useita ohjelmoijia, koska versionhallintaohjelmisto estää saman lähdekooditiedoston muuttamisen yhtäaikaa estäen tehtyjen muutosten päällekirjoittamisen. Versioiden hallitseminen Jos teet kaupallisia serialisointia käyttäviä sovelluksia, on hyvin tärkeää ylläpitää jokaisen eri tiedoston/olion skeemanumeroa niiden sovittamiseksi yhteen vanhempien versioiden kanssa. Muussa tapauksessa saatat joutua hämmentävään tilanteeseen, kun asiakkaan ohjelmaversiota päivitettäessä sovelluksen kaikki vanhat datatiedostot tulevat ylikirjoitetuiksi.

554 Sovelluksen tietojen ulkoistaminen Datan tallentaminen, lataaminen ja siirtäminen LISTAUS 23.2 LST23_2.CPP blob.cpp, Blob-dataolion luokkatoteutus 1 // ** include the standard header 2 #include "stdafx.h" 3 #include "blob.h" 4 // ** Add the implementation for serialization 5 IMPLEMENT_SERIAL(CBlob,CObject,1) 6 // ** Implement the default constructor 7 CBlob::CBlob() 8 { 9 } 1 Tällä muodostimella voidaan täpläolio luoda hiiren napautuspaikkaan ja asettaa sen arvot satunnaisiksi. 2 Draw()-funktiolla jokainen täpläolio voi piirtää itsensä saatuaan piirtopintaosoittimen näkymän OnDraw()-funktiolta. 10 // ** Implement the position constructor 11 CBlob::CBlob(CPoint ptposition) 1 12 { 13 // ** Set the random seed 14 srand(gettickcount()); 15 // ** Set the position to the specified position 16 m_ptposition = ptposition; 17 // ** Set the attributes to random values 18 m_crcolor= RGB(rand()%255,rand()%255,rand()%255); 19 m_nsize = 10 + rand()%30; 20 m_nshape = rand(); 21 } 22 void CBlob::Draw(CDC* pdc) 2 23 { 24 // ** Create and select a colored brush 25 CBrush brdraw(m_crcolor); 26 CBrush* poldbrush = pdc->selectobject(&brdraw); 27 CPen* poldpen = 28 (CPen*)pDC->SelectStockObject(NULL_PEN); 29 // ** See the random generator to the shape 30 srand(m_nshape); 31 for(int n=0;n<3;n++) 32 { 33 // ** Set the blob position and random shift 34 CPoint ptblob(m_ptposition); 35 ptblob += CPoint(rand()%m_nSize,rand()%m_nSize); 36 // ** Create and draw a rectangle to the blob size 37 CRect rcblob(ptblob,ptblob); 38 rcblob.inflaterect(m_nsize,m_nsize); 39 pdc->ellipse(rcblob); 40 } 41

Datan tallentaminen, lataaminen ja siirtäminen OSA VI LUKU 23 555 42 // ** Reselect the GDI Objects 43 pdc->selectobject(poldbrush); 44 pdc->selectobject(poldpen); 45 } Rivien 2 ja 3 #include-lauseilla määrätään kääntäjä ottamaan mukaan luokan ja MFC-luokkien määrittely. Rivin 5 IMPLEMENT_SERIAL()- makro täydentää luokan määrittelyssä käytetyn DECLARE_SERIAL()- makron. Oletusmuodostin määritellään rivillä 7. Tiedostoa ladattaessa serialisointitoiminto voi luoda nämä oliot oletusmuodostimen avulla ja alustaa ilmentymät tiedostosta luetulla datalla. Oma muodostin määritellään rivillä 11 olioiden luomiseksi hiiren napautuspaikan ja satunnaisten attribuuttiarvojen mukaisesti. Riviltä 22 alkava Draw()-funktio voi sitten piirtää nämä oliot parametrinä saamaansa näkymän piirtopintaosoitinta käyttäen. Dokumentin tietojen säilyttäminen ajon aikana Määriteltyäsi sovelluksesi luokat joudut luomaan luokista ilmentymiä (eli olioita) edustamaan käyttäjän tietoja yksittäisinä olioina. Jos luot olioita, joudut pitämään yllä tietoja niistä voidaksesi muokata dataa, ladata ja tallentaa niitä ja lopuksi tuhota ne. Kun lataat tai tallennat dokumentin dataa, joudut käymään läpi kaikki tallennettavat tiedot ja serialisoimaan jokaisen olion kerrallaan. MFC-kirjastossa on luokkia, jotka helpottavat näiden olioiden seuraamista ja tukevat serialisointia, joten ne käyvät läpi automaattisesti ilmentymät. Eräs näistä on CObArray-luokka, joka kuuluu MFC:n kokoelmaluokkiin (collection). Kyseessä on kasvatettava taulukko, joka on suunniteltu CObjectista johdettujen luokkien tallentamiseen eli se saattaa sopia kaikille määrittämillesi dataolioille. Sen lisäksi luokka ymmärtää serialisointia ja auttaa dokumentin tietojen serialisoinnissa. Voit lisätä CObArray-olion CPersistDoc-dokumenttiluokan määrittelyyn //Attributes-kommentin ja public:-määrittelyn alle näin: // Attributes public: CObArray m_blobarray(); Tämä uusi m_blobarray-olio voi nyt säilyttää ja seurata CObjectista johdettuja luokkia (kuten CBlobia). Tyyppiturvallisten mallitaulukoiden käyttö CObArray ei ole tyyppiturvallinen, koska se hyväksyy mukisematta minkä tahansa CObjectista johdetun olion. Toisinaan tällainen toiminta on paikallaan, mutta joskus taulukkoon halutaan tallentaa ainoastaan tietyntyyppisiä olioita. Tyyppien käyttöön voidaan pakottaa useiden mallien, esimerkiksi CTypedPtrArray, käytöllä. Vääräntyyppisen olion lisäämisen yrittäminen antaa tällöin assertion failed -varoitussanoman.

556 Sovelluksen tietojen ulkoistaminen Datan tallentaminen, lataaminen ja siirtäminen Olioiden säilyttämisen lisäksi dokumentti joutuu tuhoamaan ne käyttäjän sulkiessa sovelluksen. Voit toteuttaa tämän lisäämällä listauksen 23.3 funktion sekä vastaavan määrittelyn luokan määrittelyyn: void DeleteBlobs(); LISTAUS 23.3 LST23_3.CPP DeleteBlobs()-luokan toteutus ja käyttö kaikkien varattujen Blob-olioiden poistamiseksi 1 DeleteBlobs()-funktio käy läpi kaikki täplät ja tuhoaa olioilmentymän varaaman muistin ja tyhjentää lopuksi olioita sisältävän taulukon. 2 Uuden dokumentin on tuhottava vanhat täplät, koska SDI-sovellusrunko käyttää samaa dokumenttioliota uudelleen. 1 void CPersistDoc::DeleteBlobs() 1 2 { 3 // ** Delete the allocated blobs 4 for(int i=0;i<m_blobarray.getsize();i++) 5 delete m_blobarray.getat(i); 6 m_blobarray.removeall(); 7 } 8 CPersistDoc::~CPersistDoc() 9 { 10 DeleteBlobs(); 11 } 12 BOOL CPersistDoc::OnNewDocument() 13 { 14 if (!CDocument::OnNewDocument()) 15 return FALSE; 16 // TODO: add reinitialization code here 17 // (SDI documents will reuse this document) 18 DeleteBlobs(); 2 19 return TRUE; 20 } Tämän funktion toteutus on esitetty listauksen 23.3 riveillä 1 7. DeleteBlobs()-funktio käy läpi kaikki CObArrayn CBlob-oliot ja tuhoaa jokaisen kerrallaan. Tämän jälkeen itse taulukko nollataan kutsumalla sen RemoveAll()-funktiota. Kun itse dokumentti tuhotaan, kutsutaan dokumentin tuhoajafunktiota (destructor) ja se on oikea paikka kutsua käytettävien dataolioiden tuhoamisfunktioita (rivi 10). Käyttäjä voi toki luoda uuden dokumentin vielä vanhan ollessa avoinna ja tällöin sovellusrunko ottaa vanhan dokumentin uuteen käyttöön. Tässä tapauksessa dokumentissa sijaitsevat dataoliot joudutaan nollaamaan. Voit tehdä toimet CPersistDoc::OnNewDocument()-funktiossa kutsumalla

Datan tallentaminen, lataaminen ja siirtäminen DeleteBlobs()-funktiota, kuten rivillä 18 on tehty. OSA VI LUKU 23 557 Olemme käsitelleet dataolioiden säilyttämisen ja tuhoamisen, mutta käyttäjälle tarvitaan myös keinot uusien olioiden luomiseksi ja dokumenttiin lisäämiseksi. Miten se tehdään, vaihtelee varmaankin sovelluskohtaisesti ja riippuu myös käyttöliittymästä. Luotuasi uuden dataolion voit lisätä sen sitten säilöluokkaan, kuten CObArray. CObArray-luokassa on Add()-funktio, joka tarvitsee ainoastaan yhden parametrin, osoittimen uuteen olioon. Yksinkertaisin tapa luoda noita olioita esimerkkiohjelmassa on antaa käyttäjän napauttaa hiiren painiketta missä tahansa kohden näkymää ja luoda CBlob-olio hiiren napautuksessa käytettyjen koordinaattien mukaan. Tätä varten tarvitset OnLButtonDown()- sanomankäsittelijäfunktion. Sen luominen käy luvussa 19 esitetyn ilmoitussanoman käsittelijän lisäämisohjeiden mukaan. CObArrayn käyttö Add()-jäsenfunktiolla lisäämisen sijaan haluttuun paikkaan CObArray()-taulukkoa voidaan lisätä olio InsertAt()-funktiolla (antamalla parametreinä haluttu paikka ja osoitin olioon). Luokalla on myös vastaava poistofunktio RemoveAt() sekä muuttamis- ja lukemisfunktiot SetAt() ja GetAt(). Lisää seuraavat rivit OnLButtonDown()-käsittelijään luodaksesi uuden blob-olio point-parametrin perusteella ja lisätäksesi sen dokumentissa olevaan m_blobarray-taulukkoon (//TODO-kommenttien jälkeen). GetDocument()->m_BlobArray.Add(new CBlob(point)); Invalidate(); Invalidate()-funktio saa aikaan näkymän ja myös uusien olioiden uudelleenpiirtämisen listauksen 23.4 koodin avulla. LISTAUS 23.4 LST23_4.CPP Täplien piirtäminen OnDraw()-funktiosta 1 void CPersistView::OnDraw(CDC* pdc) 2 { 3 CPersistDoc* pdoc = GetDocument(); 4 ASSERT_VALID(pDoc); 5 6 // TODO: add draw code for native data here 7 8 for(int i=0;i<pdoc->m_blobarray.getsize();i++) 1 9 { 10 CBlob* pblob = (CBlob*)pDoc->m_BlobArray.GetAt(i); 11 pblob->draw(pdc); 12 } 13 } 1 Näkymä yksinkertaisesti käy läpi kaikki täplät (blob-oliot) ja pyytää kutakin piirtämään itsensä. Listauksessa 23.4 oliot käydään läpi riveillä 8 12 ja jokaisen olion Draw()-funktiota kutsutaan (rivi 11). Kääntäjä tarvitsee lisäksi luokan määrittelyn:

558 Sovelluksen tietojen ulkoistaminen Datan tallentaminen, lataaminen ja siirtäminen #include blob.h Voit lisätä tämän muiden #include-lauseiden jälkeen PersistView.cpp tiedostoon. Kun käännät ja ajat sovelluksesi, voit napauttaa hiiren vasemmalla painikkeella näkymäikkunassa ja lisätä uusia täpliä (blob), kuten kuva 23.2 osoittaa. KUVA 23.2 Blob-olioiden näyttäminen Persist-sovelluksesta KATSO MYÖS Lisätietoja dokumentista ja dokumentin datasta luvusta 12. Täytettyjen muotojen piirtäminen piirtopinnalle luvussa 16. Dataolioiden serialisointi Jotta voisit serialisoida dataoliosi, joudut lisäämään luokkaasi Serialize()-funktion, jolla jäsenmuuttujista muodostetaan peräkkäinen luettelo, joka voidaan ladata tiedostosta tai tallentaa tiedostoon. Serialize()-virtuaalifunktio on määritelty seuraavasti: // ** Add the Serialize Override virtual void Serialize(CArchive& ar);

Datan tallentaminen, lataaminen ja siirtäminen Edellä esitetty Serialize()-funktion määrittely lisätään luokan määrittelytiedostoon (esimerkiksi blob.h). Vastaava Serialize()- funktion toteutuskoodi tulee sitten lisätä luokan toteutustiedostoon (esimerkiksi blob.cpp). Levytiedosto on upotettu CArchive-olioon, jonka Serialize()- funktio saa parametrinä sovellusrungolta. OSA VI LUKU 23 559 CArchive-olion avulla dokumentin data saadaan helposti luetteloksi ja siinä on tieto tiedonsiirron suunnasta eli tallennetaanko tietoja vai ladataanko niitä. Käyttäjän valitessa dokumentin lataamisen tai tallentamisen sovellusrunko luo automaattisesti CArchive-olion ja avaa tiedoston valmiiksi tiedonsiirtoa varten. Sen jälkeen se kutsuu dokumentin omaa Serialize()-funktiota välittäen sille CArchive-olion parametrinä. CArchive-luokkaan on määritelty useita toimintoja, kuten operaattorit << ja >>. Näitä käytetään datan siirtämiseen CArchive-olioon (tiedostoon). Operaattoreilla voidaan tallentaa arvo näin: ar << m_myvar ja ladata arvo tiedostosta näin: Virtuaalifunktioiden lisääminen omiin luokkiin Jos olet käyttänyt ClassViewsivun pikavalikosta saatavaa New Virtual Override -valintaikkunaa, huomaat, ettei sillä voi lisätä virtuaalifunktioita omiin luokkiin. Joudut sen sijaan lisäämään manuaalisesti funktion määrittely- ja toteutuskoodin luokkasi määrittelytiedostoon (.h) ja toteutustiedostoon (.cpp) tekstieditoria käyttäen. ar >> m_myvar Kun kirjoitat olion Serialize()-funktiota, voit tutkia, tallennetaanko vai ladataanko oliota käyttämällä CArchive-olion jäsenfunktioita IsStoring() ja IsLoading(). Tavallisesti kukin jäsenmuuttuja tallennetaan tai ladataan omalla << tai >>-operaattoria käyttävällä rivillään. Tämä on esitetty CBlob-esimerkkioliolle listauksessa 23.5. LISTAUS 23.5 LST23_5.CPP Serialisoinnin toteutuksen lisääminen CBlob-luokkaan 1 void CBlob::Serialize(CArchive& ar) 2 { 3 CObject::Serialize(ar); 4 if (ar.isstoring()) 5 { 6 ar << m_ptposition; 1 7 ar << m_crcolor; 8 ar << m_nsize; 9 ar << m_nshape; 10 } 11 else 12 { 13 ar >> m_ptposition; 1 14 ar >> m_crcolor; 15 ar >> m_nsize; 16 ar >> m_nshape; 17 } 18 } 1 Tallennettaessa jäsenmuuttujat lisätään arkistoon (Archive). 2 Ladattaessa arkisto puretaan jäsenmuuttujiin.

560 Sovelluksen tietojen ulkoistaminen Datan tallentaminen, lataaminen ja siirtäminen Listauksen 23.5 rivillä 4 kutsutaan CArchive-luokan jäsenfunktiota IsStoring() selvittämään, tallentaako vai lataako CArchive-olio dataa. Tallennettaessa data tulee siirtää CArchive-olioon ja ladatessa lukea se siitä. Datan tallennus tehdään riveillä 6 9. <<-operaattori välittää blob-luokan kunkin jäsenen CArchive-oliolle, jossa arvo lisätään levytiedostoon. Sama tehdään päinvastoin riveillä 13 16 ja >>-operaattori alustaa jäsenmuuttujan CArchive-oliosta luetulla arvolla. Joudut kutsumaan jokaisen dokumenttisi olion Serialize()-funktiota olion tallentamiseksi tai lataamiseksi. Tämä käy muokkaamalla dokumentin omaa Serialize()-funktiota kutsumaan olioiden Serialize()-funktioita. Dokumentin tietojen serialisoiminen Useimmat sovellukset todennäköisesti tallentavat esimerkkiämme enemmän ja mutkikkaampia tietoja. Joka tapauksessa dokumentin Serialize()-funktio tarjoaa hyvän aloituspisteen koko sovelluksen tietojen tallentamiselle. Joudut todennäköisesti lisäämään dokumentin Serialize()-funktioon useita taulukoita tai kehittyneempiä kokoelmaolioita sovelluksesi tietojen tallentamiseksi ja lataamiseksi. Olioiden säilyttäminen CObArray-taulukossa (kuten esimerkin m_blobarrayssä) tekee tästä huomattavasti helpompaa. CObArray tukee serialisointia ja se osaa käydä läpi säilyttämänsä oliot ja tallentaa ne. Vastaavasti uutta dokumenttia levyltä avattaessa CObArray-olio huomaa, kuinka monta oliota se tulee säilyttämään ja minkä tyyppisiä ne ovat, joten se osaa luoda oliot puolestasi (sillä oletusmuodostimella) ja kustua sitten kunkin olion Serialize()-funktiota olion tietojen alustamiseksi tiedostosta. Tämä tarkoittaa, että joudut kutsumaan ainoastaan oliotaulukon Serialize()-funktiota, esimerkiksi näin: void CPersistDoc::Serialize(CArchive& ar) { m_blobarray.serialize(ar); } Voit tehdä nämä muutokset esimerkkiohjelmaan ja kääntää ja ajaa sen nähdäksesi, kuinka serialisointikoodi lataa ja tallentaa täpläolioita (blob). Seuraavaksi esitellään esimerkkiohjelman täpläolioiden tallentaminen ja lataaminen. Piirrä ohjelmalla muutamia täpliä ikkunassa napauttamalla. Valitse sitten File-valikosta Save As. Sovellusrunko avaa automaattisesti Save As valintaikkunan, jossa voit muuttaa tiedoston oletusnimen Untitled.blb valitsemaksi blob-tiedostoksi. Jos muutat nimen ja napautat Save, serialisointi tehdään ja täplätiedot tallentuvat levylle. Voit varmistaa tämän sulkemalla sovelluksen, käynnistämällä sen uudelleen ja valitsemalla File-valikosta Open. Koska AppWizardissa tiedostotyypiksi määrättiin.blb, näet aluksi ainoastaan blob-tiedostot, joten tallentamasi tiedoston tulisi olla ainoa valittavissa oleva. Valitse se ja lataa se uudelleen sovellukseen Open-painikkeella. Nyt aiemmin

Datan tallentaminen, lataaminen ja siirtäminen piirtämäsi täplät ovat ikkunassa jälleen omilla paikoillaan. Voit nyt luoda uusia täpliä ja tallentaa ne uudelleen tai luoda uuden dokumentin ja tallentaa sen eri nimelle ja käsitellä tiedostoja kuten muissakin sovelluksissa. Voit sulkea tietokoneesi ja tulla takaisin kahden viikon päästä samat täplät ovat yhä samoissa paikoissa, mihin ne edellisellä kerralla piirsit. OSA VI LUKU 23 561 Viimeksi avattujen tiedostojen luettelon käyttö Sovellusrunko tarjoaa vielä kaiken edellisen lisäksi luettelon viimeksi avatuista tiedostoista. Jos olet tallentanut useita eri nimisiä blobtiedostoja, olet saattanut huomata File-vaikossa luettelon viimeksi avatuista tiedostoista. Voit helposti valita minkä tahansa näistä avattavaksi suoraan valikosta. Dokumenttityyppien rekisteröiminen Olet varmaan kokenut, kuinka suoraan dokumenttitiedoston nimeä kaksoisnapauttamalla saadaan avattua dokumenttiin liitetty Windowssovellus. Kyseessä on rekisteröityjen tiedostotyyppien käyttö; lisäämällä sovellukseen pari koodiriviä saat samat toiminnot omaan sovellukseesi. Nämä koodirivit tulee lisätä sovellusluokkasi ( App) InitInstance()-funktioon välittömästi AddDocTemplate(pDocTemplate); -rivin jälkeen: CRecentFileList-luokan käyttö SDI- ja MDI-vakiosovellukset käyttävät CRecentFileList-luokkaa viimeksi avattujen tiedostojen luettelona. Voit käyttää tätä luokkaa suoraan (eikä sovellusrungon kautta) toteuttamaan oman viimeksi käytettyjen tiedstojen luettelon ja liittämään sen omiin valikkoihin. CRecentFileList-luokalle voidaan määrittää kunkin tiedoston näytettävä nimi ja tiedostopolku. Se osaa automaattisesti päivittää valikkoa tiedoston lisäämiseksi tai poistamiseksi. RegisterShellFileTypes(); EnableShellOpen(); KATSO MYÖS Lisätietoja dokumentista ja sen datasta luvussa 12. Tiedostojen käsittely SDI- ja MDI-sovelluksissa, jotka joutuvat tallentamaan dokumentin tietoja, on serialisointi erittäin käyttökelpoinen menettely. Joskus tiedostoja joudutaan kuitenkin luomaan, lukemaan ja kirjoittamaan suoraan. MFC-kirjasto tarjoaa käyttöön levytiedoston paketoivan luokan CFile. Tähän luokkaan kätkeytyvät kaikki tiedosto-operaatiot sekä tiedostoon liittyvät attribuutit. Luomalla ja käyttämällä CFile-olioita voit myös luoda, lukea ja kirjoittaa levytiedostoja CFile-luokan funktioiden avulla.

562 Sovelluksen tietojen ulkoistaminen Datan tallentaminen, lataaminen ja siirtäminen Käytitpä sitten dokumentin datan serialisointia tai suoraan tiedostoon kirjoittamista, päädyt kuitenkin käyttämään CFile-luokkaa tai siitä johdettua luokkaa. Serialisoinnin käyttämä CArchive-luokka yhdistyy CFile-olioon varsinaista dokumentin tietojen lukemista tai kirjoittamista varten. Tässä kappaleessa esitetään, kuinka CFiletoimii sekä tutustutaan CFile-luokan spesifisempiin versioihin. Tiedostokahvat Useiden MFC-luokkien tavoin myös CFile-luokka paketoi Win32-tiedostokahvan. Voit käyttää tätä kahvaa suoraan CFileolion m_hfile-jäsenmuuttujasta. Ellei tiedostoa ole avattu tai luotu, kahvan arvo on CFile::hFileNull, muutoin siinä on nykyisen tiedoston kahva. CFile-luokan käyttö Saat muodostettua CFile-olion kolmella tavalla. Yksinkertaisin muodostin ei tarvitse parametrejä ja luo avaamattoman tiedosto-olion, jonka Open()-funktiota kutsutaan myöhemmin levytiedoston luomiseksi tai avaamiseksi. Toinen muodostinversio käyttää yhtä parametriä (hfile-kahva), jonka tulee olla valmiiksi avattu tiedosto. Tällä voidaan ottaa käyttöön CFile-olio jo valmiiksi avatulle tiedostolle. Kolmas muodostinversio käyttää kahta parametriä: ensimmäinen on avattavan tai luotavan tiedoston nimi ja hakemistopolku ja toinen yhdistelmä mahdollisista tiedostonavauslipuista. Tiedostojen avaaminen Eräs kaikkein tärkeimmistä tiedostonkäsittelytoimista on aluksi tehtävä tiedoston avaaminen. Määrittämällä avaamislippuja kerrot etukäteen, kuinka haluat annettua tiedostonimeä käsiteltävän. Tahdot ehkä aina luoda uuden tiedoston, avata tiedoston ainoastaan luettavaksi (readonly) tai sekä luettavaksi että kirjoitettavaksi. Voit antaa Open()- funktiolle toisena parametrinä (nopenflags) useita erilaisia lukemiseen ja kirjoittamiseen liittyviä lippuja (taulukko 23.1). Ensimmäinen Open()-funktion parametri on avattavan tai luotavan tiedoston nimi. Voit haluttaessa yhdistää joitakin lippujen arvoja, esimerkiksi näin: CFile filemyfile; FileMyFile.Open( MyFile.txt, CFile::modeCreate + CFile::modeNoTruncate); Näillä lipuilla avataan tiedosto MyFile.txt, mikäli se on jo olemassa; muutoin luodaan samanniminen uusi tiedosto. Mikäli olisi käytetty ainoastaan lippua CFile::modeCreate, uusi tiedosto olisi luotu, vaikka vanhakin olisi ollut olemassa, joten CFile::modeNoTruncatelippu muuttaa CFile::modeCreate-lipun vaikutusta siten, ettei tiedostoja typistetä (truncate) nollan tavun mittaisiksi. Tässä liput on yhdistetty +-operaattorilla, mutta yhtä hyvin olisi voitu käyttää - operaattoria (TAI), esimerkiksi näin: CFile filemyfile;

Datan tallentaminen, lataaminen ja siirtäminen FileMyFile.Open( MyFile.txt, CFile::modeCreate CFile::modeNoTruncate); Tämä koodi toimii aivan samoin kuin edellinenkin, koska liput ovat bittikohtaista tietoa ja looginen TAI yhdistää ne aivan samoin kuin yhteenlaskukin. OSA VI LUKU 23 563 Jos tiedoston avaaminen onnistuu, Open()-funktio palauttaa TRUEarvon FALSE-paluuarvo tarkoittaa avaamisen epäonnistumista. Open()-funktiolle voidaan valinnaisesti välittää kolmantena parametrinä CFileException-osoitin, jonka osoittamassa CFileException-oliossa on funktion suorittamisen jälkeen tiedot avaamisen mahdollisen epäonnistumisen syistä. TAULUKKO 23.1 Tiedoston avaamiseen tarkoitetut CFile::Open()-funktiolle syötettävät liput Lippu CFile::modeCreate CFile::modeNoTruncate CFile::modeRead CFile::modeWrite CFile::modeReadWrite CFile::shareDenyNone CFile::shareExclusive CFile::shareDenyRead CFile::shareDenyWrite CFile::typeText CFile::typeBinary Kuvaus Luo aina uuden tiedoston (vaikka samanniminen tiedosto olisi olemassa). Tämä lippu voidaan yhdistää CFile::modeCreatelipun kanssa haluttaessa luoda uusi tiedosto, mikäli samannimistä ei ole olemassa ja muuten avata nimetty tiedosto. Tiedosto avataan vain luettavaksi siihen ei voi kirjoittaa. Tiedosto avataan vain kirjoitettavaksi siitä ei voi lukea. Tiedosto avataan sekä lukemista että kirjoitta mista varten. Muut prosessit voivat lukea ja kirjoittaa tiedostoon. Muut prosessit eivät voi lukea ja kirjoittaa tiedostoon. Muut prosessit eivät voi lukea avatusta tiedostosta. Muut prosessit eivät voi kirjoittaa avattuun tiedostoon. Jotkut johdetuista luokista hyödyntävät tätä tekstinkäsittelyyn. Ei muokkaa merkkejä tiedostosta luettaessa tai siihen kirjoitettaessa. Jotkut johdetuista luokista vaativat tämän lipun. CFileException-olion käyttö Jos tiedostoa avattaessa sattuu virhe, välitetään ohjelmalle CFileException-olio. Virheen syy voidaan lukea CFileExceptionolion m_cause-jäsenmuuttujasta (CFileException-olion omat numerokoodit) tai m_ioserrorjäsenmuuttujasta (käyttöjärjestelmän virhekoodit). Tavallisimpia m_cause-muuttujan arvoja ovat CFileException::fileNotFound, CFileException::accessDenied ja CFileException::diskFull.

564 Puskurin lopun ohi lukeminen Ole tarkkana, ettet pyydä Read()- toimintoa lukemaan enempää tavuja kuin puskuriisi mahtuu. Tällaisessa tapauksessa saatetaan kirjoittaa ohjelman muiden osien päälle ja saadaan varmasti ohjelma kaatumaan tai muita ennakoimattomia ongelmia. Sovelluksen tietojen ulkoistaminen Datan tallentaminen, lataaminen ja siirtäminen Tiedoston lukeminen ja kirjoittaminen Kun tiedosto on avattu, voit lukea sitä ja kirjoittaa siihen avausmoodin mukaisesti. Lukemista ja kirjoittamista varten CFile-luokassa on Read()- ja Write()-funktiot sekä niihin liitetty tiedosto-osoitin. Kun tiedosto on avattu, osoitetaan tiedoston alkuun. Jos tiedostosta luetaan 200 tavua, paikkaa päivitetään ja seuraava Read()-funktio lukeekin tietoa 200 tavun päästä tiedoston alusta. Tässä luvussa esitetään myöhemmin, kuinka tiedosto-osoitinta voidaan muokata. Tyypillinen Read()-funktion käyttö näyttäisi esimerkiksi tältä: CFile myfile( MyFile.txt,CFile::modeRead); char armyreadbuffer[200]; UINT ubytesread = myfile.read(armyreadbuffer,sizeof(armyreadbuffer)); Read()-funktio saa kaksi parametriä. Ensimmäinen on kohdepuskurin osoite. Tähän puskuriin kirjoitetaan kaikki luettu tieto. Toinen parametri kertoo Read()-funktiolle, kuinka monta tavua halutaan lukea; tavuja voi olla vain muutama tai sitten esimerkin tapaan vaikkapa puskurin koko. Kun Read()-funktio on suoritettu, palautetaan luettujen tavujen määrä. Tämä voi olla sama kuin niiden tavujen määrä, jotka oli määrä lukea tai tiedoston loppu kohdattaessa vähemmän mikä kertoo, että kaikki saatavilla olevat tavut oli luettu. Jos paluuarvo on nolla, tiedostossa ei ole jäljellä tavuja luettavaksi. Tämä voidaan kokeilla käytännössä yksinkertaisella valintaikkunapohjaisella (dialog-based) editorisovelluksella. Lisäät siis koodia valintaikkunan OnInitDialog()-käsittelijäfunktioon tekstin lukemiseksi tiedostosta, sen muokkaamiseksi ja tallentamiseksi takaisin tiedostoon OK-painiketta painettaessa. Ohjeet tämän FileEdit-valintaikkunasovelluksen tekemiseksi AppWizardilla löydät luvusta 5. Tämän jälkeen lisäät suuren tekstiruudun (edit control) pääikkunaan ja asetat sen MultiLine-tyylin käytettäväksi. Liitä vielä ClassWizardilla CString-tyyppinen m_editbox-muuttuja tekstiruutuun (ohjeet myös luvussa 5). Kun olet lisännyt listauksen 23.6 koodin CFileEditDlg-luokan OnInitDialog()-funktioon, voit lukea tekstin ohjelmaan kiinteästi koodatusta C:\MyFile.txt-tiedostosta.

Datan tallentaminen, lataaminen ja siirtäminen LISTAUS 23.6 LST23_6.CPP - Tiedoston sisällön lukeminen tekstikontrolliin OSA VI LUKU 23 565 1 // TODO: Add extra initialization here 2 3 // ** Declare and open a file object for reading 4 CFile fileedittext; 5 if (fileedittext.open("c:\\myfile.txt",cfile::moderead)) 6 { 7 // ** Declare a large buffer for reading the text 8 char cbuf[512]; 9 UINT ubytesread; 10 11 // ** Continue reading the file until no more data is read 12 while(ubytesread = 13 fileedittext.read(cbuf,sizeof(cbuf)-1)) 1 14 { 15 // ** Null terminate after the last character 16 cbuf[ubytesread] = NULL; 17 18 // ** Add the buffer to the mapped CString 19 m_editbox += CString(cBuf); 20 } 21 22 // ** Close the file 23 fileedittext.close(); 24 25 // ** Send the m_editbox string to the edit control 26 UpdateData(FALSE); 27 } Listauksessa 23.6 CFile-luokan olio fileedittext määritellään rivillä 4 ja avataan rivillä 5 ohjelmaan kiinteästi koodatusta tiedostosta C:\MyFile.txt. Read()-funktio rivillä 13 käyttää rivillä 8 määriteltyä puskuria tiedostosta luettavien tavujen tallentamiseen. Read()-funktion toinen parametri määrittää, että luettavien tavujen määrä on yhtä pienempi kuin puskurin koko. Syy tähän on, että tiedostosta luettujen tavujen perään voitaisiin vielä lisätä NULL-merkki, jolloin puskuriin saadaan yksi nollaan päättyvä merkkijono (null terminated string). Kun merkkijono on päätetty NULL-merkillä, se voidaan muuntaa CStringolioksi ja lisätä CString-merkkijonon m_editbox loppuun rivillä 19. Jos tiedosto on ensimmäisellä lukukerralla pidempi kuin puskuri, koko toimintoa toistetaan, kunnes tiedosto on saatu luettua kokonaan. Kun Read()-funktio asettaa ubytesread-arvon nollaksi, while-silmukka päättyy ja tiedosto suljetaan Close()-funktiolla (rivillä 23). Teksti- Kenoviivan (\) käyttö Huomaa, että koodissa rivillä 5 on kaksi kenoviiva. Kyseessä ei ole kirjoitusvirhe, vaan kenoviivaa käytetään C-kielessä (ja C++:ssa) erikoismerkkien merkitsemiseen, kuten \n (rivinvaihto), \r (telanpalautus) ja \b (korjaus). Tästä syystä jokainen \ pitää esittää merkinnällä \\. 1 Tätä while-silmukkaa toistetaan, kunnes Read()-funktio palauttaa arvon, joka kertoo, ettei tavuja enää luettu. Tällöin ollaan tiedoston lopussa.

566 Nollaan päättyvät merkkijonot Nollaan päättyvä merkkijono (null-terminated string) on (yksiulotteinen) merkkitaulukko, jossa varsinaisten merkkien jälkeen on NULL-merkki (nolla) ilmoittamassa merkkijonon loppumista. Nollaan päättyvät merkkijonot ovat yleisiä C- koodissa ja niiden kanssa voidaan käyttää useita funktioita. Esimerkiksi strlen() palauttaa merkkijonon pituuden ja strcpy()- funktiolla voidaan kopioida toisena parametrinä annettu merkkijono ensimmäiseen. strcmp()-funktio puolestaan vertaa kahta merkkijonoa ja palauttaa nollan, jos ne ovat samoja. Näiden ja monien muiden vastaavien funktioiden dokumentointi löytyy Microsoftin sähköisestä manuaalista String Manipulation Routines -otsikon alta. Näitä funktioita käytettäessä on toteutustiedostoon otettava mukaan #include-lauseella string.h-tiedosto. 1 Koko tekstikontrollin teksti voidaan tulostaa yhdellä Write()- funktiolla, koska sen pituus tunnetaan etukäteen. Sovelluksen tietojen ulkoistaminen Datan tallentaminen, lataaminen ja siirtäminen kontrolliin liitetyn m_editbox-muuttujan sisältö päivitetään kontrolliin rivin 26 funktiolla UpdateData(FALSE). Tässä on editorisovelluksen lukeva osa kokonaisuudessaan. Kun käännät ja ajat sovelluksen näiden rivien lisäämisen jälkeen, saat sovellukseen esiin C:\MyFile.txt tiedoston sisältämän tekstin. Voit luoda tuon tiedoston esimerkiksi Windowsin Muistiolla (Notepad) kirjoittamalla siinä tekstiä ja tallentamalla sen tiedostoon C:\MyFile.txt. Käyttäjän painettua OK-painiketta tekstin muuttamisen jälkeen joudut kirjoittaman muutokset takaisin tiedostoon. Tämä onnistuu aina luomalla uusi tiedosto (siis kirjoittamalla se vanhan päälle) ja käyttämällä Write()-funktiota tekstiruutuun liitetyn CString-muuttujan sisällön kirjoittamiseen tiedostoon. Lisää ClassWizardilla OK-painikkeelle BN_CLICKED-käsittelijä nimeltään OnOK tekstiruudun sisällön tallettavaa koodia varten (listaus 23.7). Löydät lisätietoja BN_CLICKED-käsittelijän lisäämisestä luvusta 4. LISTAUS 23.7 LST23_7.CPP Tekstiruudun tietojen kirjoittaminen levytiedostoon 1 void CFileEditDlg::OnOK() 2 { 3 // TODO: Add extra validation here 4 5 // ** Set the m_editbox string from the edit control 6 UpdateData(TRUE); 7 8 // ** Declare and open a file object for writing 9 CFile fileedittext; 10 if (fileedittext.open("c:\\myfile.txt", 11 CFile::modeCreate + CFile::modeWrite)) 12 { 13 // ** Write out the full string 14 fileedittext.write((const char*lpcstr) 15 m_editbox,m_editbox.getlength()); 1 16 17 // ** Close the file 18 fileedittext.close(); 19 } 20 21 CDialog::OnOK(); 22 }