Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: VB6: Ohjelma hävittää oletustiedot

Sivun loppuun

kisahalo [03.12.2010 09:31:34]

#

Ongelmani on se, että ohjelmani hävittää käynnistyksessä vähän väliä oletusasetukset. Kun pitäisi sijoittaa tekstikenttään esimerkiksi lämpötilaksi 22, silloin tällöin siihen ilmaantuu tyyliin "102011356". Eräät kolme single-muuttujaa latautuvat usein nollina. Missä on vika?

Olen tallentanut kaiken "tiedot"-nimiseen luokkaan esim. näin:

'OK-nappia painettaessa
tiedot.Aikavali = Int(aikatext.text)
Call AloitusForm.TallenaTiedostoon

Ohjelman käynnistyessä tekstikentät täytetään vastaavalla tavalla, esim. aikatext.text = tiedot.Aikavali. Tiedot tallennetaan seuraavanlaiseen luokkaan, joka on globaalisti käytettävissä moduulissa:

Type Tallennustiedot
    Aikavali as Integer
    Raakadata(27,27,5) As Double
    Temp As Single
    Raja1 As Single
    Raja2 As Single
    'jne.
End Type

Public tiedot As Tallennustiedot

Oletusasetukset haetaan binääritiedostosta alustukset.dat seuraavalla koodilla:

Public Sub HaeTiedotTiedostosta()
Dim nAvaus As Integer

   nAvaus = FreeFile

   'avataan
   Open App.path & "\alustukset.dat" For Binary As #nAvaus
   'sama luokka "tiedot" sisältää kaiken datan
   Get #nAvaus, , tiedot

   Close #nAvaus

End sub

Tallennus taas menee vastaavasti:

Public Sub TallennaTiedostoon()
Dim nAvaus As Integer

   nAvaus = FreeFile

   'avataan
   Open App.path & "\alustukset.dat" For Binary As #nAvaus
   'sama luokka "tiedot" sisältää kaiken datan
   Put #nAvaus, , tiedot
   'suljetaan
   Close #nAvaus

End sub

neau33 [03.12.2010 12:44:48]

#

Moi taas kisahalo!

Aluksi, olet pukannut kaman 'tiedot' nimiseen muuttujaan, joka on ilmentymä oliosta, jonka olet nimennyt nimellä 'Tallennustiedot'.

Nyt on niin, että kun pukkaat uutta kamaa binaaritiedostoon niin tiedostoa ei luoda enää uudestaan vaan se kirjoitetaan vanhan tiedon päälle alkaen tiedoston alusta jos kohdistinta ei erikseen siirretä osoittamaan esim. tiedoston loppua. Nyt jos dataputki on pidempi, kuin edellisellä kerralla, esim. joku luku on vaikkapa 1000 ja oli edellisellä tallennuskerralla 100 ja muu tallennettava tieto on pysyy ennallaan niin tiedoston pituus kasvaa hieman verrattuna edelliseen tallennuskertaan. Mutta jos jutska onkin toisin päin eli luku oli edellisellä kerralla 1000 ja nyt 100 niin tiedoston pituus ei lyhene.
Tämä on helppo ratkaista siten , että tuhoaa vanhan tiedoston ennen uuden tallentamista.
Toinen jutska joka auttaa on, että käyttää datan erotteluun jotain erotinmerkkiä/merkkijonoa jolloin se on kätevästi splitattavissa taulukkoon eikä 'kenttien' merkkimäärien muutoksilla ole enää mitään vaikutusta.
Lopuksi, jätä FreeFile-funktion käyttö ja käytä määrittelyyn yksinkertaista: As #1 määrittelyä...

kisahalo [03.12.2010 12:52:22]

#

Kiitos vastauksesta, Nea. Miten minun pitäisi tuo tallennus tehdä, jotta se tuhoaisi edellisen tiedon (vaikka tiedostonkin) kokonaan ja kirjoittaisi uuden? Olisiko jokin muu tallennusmuoto parempi? Pahoitteluni että olen nyyppä tässä.

Minulle on joka tapauksessa tärkeintä, että voin tallettaa tiedot tuollaisena oliona, ettei tarvitsisi 3-ulotteisten matriisien dataa parsea tekstitiedostosta.

Toiseksi tuo FreeFile tuli käyttöön siksi, että ohjelma valitti toistuvasti, että käytetty numero on käytössä, vaikka mielestäni olin sulkenut sen. Onko FreeFilessa jotain pahaa? Ajattelin, että se kävisi hyvin kun kerran tiedosto avataan ja suljetaan samassa aliohjelmassa.

neau33 [03.12.2010 13:24:36]

#

Moi taas kisahalo!

esim näin...

Private Type AsetusTiedot
  asetus() As Variant
End Type

Private asetukset As AsetusTiedot

Private Sub Form_Load()

  If Dir("C:\polku\asetukset.dat") <> "" Then

     Dim fileContent As Variant, i As Integer
     Dim fileData() As String
     Open "C:\polku\asetukset.dat" For Binary Access Read As #1
     Get #1, , fileContent: Close #1
     fileData = Split(fileContent, "|"): Close #1

     Redim asetukset.asetus(UBound(fileData))

     For i = 0 To UBound(fileData)
           asetukset.asetus(i) = fileData(i)
        End Select
     Next i

  End If

End Sub

Private  Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)

   If Dir("C:\polku\asetukset.dat") <> "" Then
      Kill("C:\polku\asetukset.dat")
   End If

   Dim fileData As Variant, i As Integer

   For i = 0 To UBound(asetukset.asetus)
      fileData = fileData  & asetukset.asetus(i)
      If i < UBound(asetukset.asetus) Then
         fileData = fileData & "|"
      End If
   Next i

   Open "C:\polku\asetukset.dat" For Binary Access Write As #1
   Put #1, , fileData: Close #1

End Sub

neau33 [03.12.2010 15:07:51]

#

Moi taas kisahalo!

tutki myös oheista esimerkkiä...

Private Type AsetusTiedot
  asetus As Variant
End Type

Private asetukset(2) As AsetusTiedot
Private kokoPolku As String
Private table(1, 1, 1)

Private Sub Form_Load()

   kokoPolku = Environ("userprofile") & "\Työpöytä\asetukset.dat"

   If Dir(kokoPolku) <> "" Then
     Open kokoPolku For Binary Access Read As #1
     Get #1, , asetukset: Close #1
     MsgBox asetukset(0).asetus(1, 0, 0)
     MsgBox asetukset(1).asetus
     MsgBox asetukset(2).asetus
   End If

   table(0, 0, 0) = 1
   table(0, 0, 1) = 2
   table(0, 1, 0) = 3
   table(0, 1, 1) = 4
   table(1, 0, 0) = 5
   table(1, 0, 1) = 6
   table(1, 1, 0) = 7
   table(1, 1, 1) = 8

End Sub

Private  Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)

   If Dir(kokoPolku) <> "" Then
     Kill kokoPolku
   End If

   asetukset(0).asetus = table
   asetukset(1).asetus = 1000000000#
   asetukset(2).asetus = 100.01!
   Open kokoPolku For Binary Access Write As #1
   Put #1, , asetukset: Close #1

End Sub

kisahalo [07.12.2010 13:23:34]

#

Terve taas Nea. Katsotaan ymmärsinkö oikein jälkimmäisen esimerkin:

Ilmeisesti teet luokan, jonka ominaisuuksiin voi lisätä mitä vain. Sitten teet taulukkotyyppisen muuttujan juuri luodusta luokasta, ja lisäät muuttujaan uusia ominaisuuksia taulukon soluina. Mutta onko tuossa jokin etu siihen nähden, että lisäisi vain ominaisuuksia itse luokkaan?

Edellistä esimerkkiä en oikein ymmärrä. Onko kyseessä juuri jonkinlainen tekstin parseminen? Ilmeisesti talletat tiedot pitkänä merkkijonona, jossa erottimena on "|" ja sitten luet ne avattaessa samalla tavalla. En oikein näe, mitä matriisit tykkää tuollaisesta. :)

kisahalo [08.12.2010 09:57:54]

#

Kokeilin jälkimmäistä, se ei toimi. Ongelma on tuossa matriisien siirtelyssä, tulee vain "can't assign to array". Pitää kokeilla seuraavaksi edellistä esimerkkiä.

kisahalo [09.12.2010 10:49:42]

#

Äh, ongelma muuntui nyt täysin toiseksi:

Jälkimmäinen esimerkkisi näyttää toimivalta, mutta ongelmia tulee Variant-muuttujan kanssa. Logiikkani on seuraava: yritän säilyttää määrittelemäni Tiedot-olion ennallaan siksi, että dataa on niin paljon, että sen säilöminen pelkkiin asetukset()-taulukon indekseihin aiheuttaisi harmaita hiuksia. Siksi ajattelin käyttää asetukset()-taulukkoa tallennukseen ja siirtää dataa Tiedot-olion ja sen välillä. Esimerkki:

Public Sub Tallennatiedostoon()
   '(tiedoston avaaminen jne.)

   'sijoitetaan taulukko
   asetukset(0).asetus = Tiedot.Isodoosiarvot
   'sijoitetaan integer
   asetukset(1).asetus = Tiedot.Raja1
   'jne
End Sub

Public Sub HaeTiedotTiedostosta()
   '(tiedoston avaaminen jne.)
   Tiedot.Isodoosiarvot = asetukset(0).asetus
End Sub

Nyt ongelmaksi tulee se, että Tiedot.Isodoosiarvot on Double, eli sijoitus ei onnistu. Pitäisi ilmeisesti sijoittaa yksi kerrallaan kaikki arvot tai muuttaa Isodoosiarvot Variant-tyypiksi. Kun yritän muuttaa Variantiksi, kääntäjä valittaa, että moduuliin määritellyn olion koko on yli 64K. :/

Kysymys kuuluu: onko tähän olemassa jonkinlaista fiksua ratkaisua, vai pitääkö minun vaihtoehtoisesti A) siirrellä matriisitiedot yksi kerrallaan tai B) vain hyväksyä tuo asetukset()-taulukon indekseihin tallettaminen?

neau33 [13.12.2010 08:40:26]

#

Moi taas kisahalo!

kisahalo kirjoitti:

...Ilmeisesti teet luokan, jonka ominaisuuksiin voi lisätä mitä vain...

En oikein käsitä tarvettasi inttää jostain luokan luomisesta, kun sellaista ei missään vaiheessa luoda. Type-määritteellä alustetaan olio, joka voi sisältää vain muuttujia tai toisia olioita (jotka voivat sisältää vain muuttujia tai jne.). Luokka taas voi sisältää mm. aliohjelmia (sub programs), funktioita (functions), ominaisuuksia (properties), ja esim em. oliorakenteita (structures) jne.
Ja jotta kaikki menisi vieläkin epäselvemmäksi niin...olion jäsenen arvoiksi voidaan sijoittaa objektiviittaus luokkaan. Mikäli sijoitat objektiviittauksen olioon niin VB6 ei suostu tallentaamaan oliotasi binaaritiedostoon.

mutta kaikessa yksinkertaisuudessaan jutska menee näin...

'Module1
Private Type AsetusTiedot
   taulu(10, 10, 5) As Double 'esim.
   int1 As Integer 'esim.
   sng1 As Single 'esim.
  'jne.
End Type

Public asetukset As AsetusTiedot
'Form1
Private tiedostopolku As String

Private Sub Form_Load()

   'Ladattaessa ohjelman päälomaketta:

   'asetetaan merkkijonomuuttujan arvoksi tiedostopolku
   tiedostopolku = "c:\asetukset.dat"

   'tutkitaan ehtolauserakenteessa lytykö määritetyn
   'tiedostopolun takaa määritetty tiedosto...
   If Dir(tiedostopolku) <> "" Then
      'ja jos löytyy niin avataan ko. tiedosto
      'lukuoikeuksin, luetaan tiedoston data
      'oliomuuttujan arvo(i)ksi ja suljetaan tiedosto.
      Open tiedostopolku For Binary Access Read As #1
      Get #1, , asetukset: Close #1
      'tähän koodia jolla haet arvoja oliomuuttujasta
      'ja sijoittelet haluamiesi muuttujien arvoiksi...
   End If

End Sub

Private  Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)

   'Ohjelman päälomaketta suljettaessa:

   'jos määritetyn tiedostopolun päästä
   'löytyy polussa määritetty tiedosto niin...
   If Dir(tiedostopolku) <> "" Then
      'tapetaan ko. tiedosto!
      Kill tiedostopolku
   End If

   'luodaan uusi binaaritiedosto merkkijonomuuttujassa
   'tiedostopolku' määritettyyn hakemistoon samaisessa
   'muuttujassa määritetyllä tiedostonimellä...
   Open tiedostopolku For Binary Access Write As #1
   'ja kirjoitetaan 'tämänhetkiset' asetukset
   'nyt luotuun tiedostoon ja suljetaan tiedosto.
   Put #1, , asetukset: Close #1

End Sub

"vähän lisävalaistusta..?"

Private Type OlioTyyppi
   kama As Variant
   nimi As String
End Type

Private oliot() As OlioTyyppi
Private arvotosi As Boolean
Private luotu As Boolean

Private Sub Command1_Click()

   If arvotosi Then Exit Sub

   Dim Bytes() As Byte
   Open "c:\windows\system32\notepad.exe" _
   For Binary Access Read As #1
   Get #1, , Bytes: Close #1
   Dim ub As Integer
   On Error Resume Next
   ub = UBound(oliot)
   If Err <> 0 Then
      Err.Clear
      On Error GoTo o
      ReDim oliot(0)
   Else
      ReDim Preserve oliot(UBound(oliot) + 1)
   End If
   oliot(UBound(oliot)).kama = Bytes: Erase Bytes
   oliot(UBound(oliot)).nimi = "notepad.exe"
   arvotosi = True

End Sub

Private Sub Command2_Click()

   If Not arvotosi or luotu Then Exit Sub

   Dim laskuriarvo As integer
   For laskuriarvo = LBound(oliot) To UBound(oliot)
      If oliot(laskuriarvo).nimi = "notepad.exe" Then
          Open App.Path & "\" & oliot(laskuriarvo).nimi _
          For Binary Access Write As #1
          Put #1, , oliot(laskuriarvo).kama: Close #1
          Do While Dir(App.Path & "\" & _
          oliot(laskuriarvo).nimi)) = "": DoEvents: Loop
          Shell App.Path & "\" & oliot(laskuriarvo).nimi
          luotu = True: Exit Sub
      End If
   Next

End Sub

kisahalo [13.12.2010 10:21:30]

#

Olen pahoillani terminologian epätarkkuudesta, kyseessä on vain se, että käytin väärää sanaa. Kiitos kärsivällisyydestä tällaisen aloittelijan kanssa. :)

Kokeilen näitä tänään ja palaan asiaan.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta