Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: VB.NET: VB.net Streamreader

Sivun loppuun

AM [20.07.2005 13:56:38]

#

Moro,

Miten streamreaderin readlineä käsketään lukemaan vain jokin tietty rivi streamin keskeltä?

Esim.
Tiedostossa on kolme riviä:
rivi 1
rivi 2
rivi 3

Haluan lukea tiedostosta pelkästään rivin 2. En halua käydä koko tiedostoa läpi ja katsoa jos rivi on kaksi, vain haluan lukea siis pelkästään tuon rivin 2. Miten onnistuu?

Ja haluan nimenomaan käyttää streamreaderia tuohon :)

esakom [21.07.2005 10:24:23]

#

joudut lukemaan rivejä alusta kunnes tulet haluamallesi riville

Dim oRead As System.IO.StreamReader
'avaa oread jossain...
'kutsu seuraavaa kunnes olet saanut haluamasi rivin
LineIn = oRead.ReadLine()

eli käytännössä voit vaikka tehdä funktion joka ottaa parametrina ton streamin ja halutun rivin indeksin. Sitten vain funktiossa luet silmukassa readlinella niin monta kertaa että saat haluamasi rivin jonka sitten palautat funktiosta ulos.

AM [21.07.2005 15:32:21]

#

esakom kirjoitti:

joudut lukemaan rivejä alusta kunnes tulet haluamallesi riville

Dim oRead As System.IO.StreamReader
'avaa oread jossain...
'kutsu seuraavaa kunnes olet saanut haluamasi rivin
LineIn = oRead.ReadLine()

eli käytännössä voit vaikka tehdä funktion joka ottaa parametrina ton streamin ja halutun rivin indeksin. Sitten vain funktiossa luet silmukassa readlinella niin monta kertaa että saat haluamasi rivin jonka sitten palautat funktiosta ulos.

Juu, juuri noin oon tuon homman tällä hetkellä toteuttanutkin. Mutta halusin nimenomaan lukea jonkin tietyn rivin, ja pelkästään sen tietyn rivin sieltä tiedostosta. On hölmöä lukea streamista kaikki rivit, jos en tarvitse kuin yhtä sieltä keskeltä.

Kikkare jossa tuota readlineä tarvitsen on oma tekemäni windows service joka pyörii koko ajan taustalla windoksessa. Pitää yrittää tehdä ko. servicestä mahdollisimman kevyt ja sen takia haluaisin juurikin lukea vain sen yhden rivin missä tiedän haluamani tekstin olevan.

Eikö todella ole mahdollista käskeä streamreaderin readlineä lukemaan vain jokin ennalta määrätty rivinumero?

Metabolix [21.07.2005 15:47:56]

#

Mieti hetki tekstitiedoston rakennetta levyllä, niin ymmärrät helposti tuonkin asian. Tiedosto ei ole levyllä riveinä vaan jatkuvana merkkijonona, jossa tietyt merkit tarkoittavat rivinvaihtoja. Ohjelmalla ei siis ole mitään muuta tapaa löytää tiettyä riviä kuin lukea eteenpäin kunnes on ohitettu tietty määrä rivinvaihtomerkkejä.

AM [21.07.2005 16:42:06]

#

Metabolix kirjoitti:

Mieti hetki tekstitiedoston rakennetta levyllä, niin ymmärrät helposti tuonkin asian. Tiedosto ei ole levyllä riveinä vaan jatkuvana merkkijonona, jossa tietyt merkit tarkoittavat rivinvaihtoja. Ohjelmalla ei siis ole mitään muuta tapaa löytää tiettyä riviä kuin lukea eteenpäin kunnes on ohitettu tietty määrä rivinvaihtomerkkejä.

Aivan, hyvä kommentti.

Mikä olisi kevyein tapa lukea 250 rivisestä tiedostosta rivi nro 113 tietyin väliajoin? Miten raskasta on käydä tosiaan nuo kaikki läpi tuolla nykyisellä tavalla, siis sillä minkä esakom:kin mainitsi? Onko streamreader tähän paras(nopein) vaihtoehto?

Metabolix [21.07.2005 17:21:27]

#

No ei se kevyttäkään ole. Riippuu paljolti rivien pituudesta. Jos tuo ei kuitenkaan ole aikakriittinen kohta eikä "tietyi väliajoin" tarkoita mitään sekuntien kokoluokkaa, niin mikään katastrofi tuo tuskin on. Mitähän varten tuon kokoisesta tiedostosta pitää jatkuvasti lukea samaa riviä? Mikä sitä muuttaa, olisiko jotenkin mahdollista pitää yhteyttä pienemmillä tiedostoilla tai esimerkiksi piipuilla?

AM [21.07.2005 17:44:12]

#

Metabolix kirjoitti:

No ei se kevyttäkään ole. Riippuu paljolti rivien pituudesta. Jos tuo ei kuitenkaan ole aikakriittinen kohta eikä "tietyi väliajoin" tarkoita mitään sekuntien kokoluokkaa, niin mikään katastrofi tuo tuskin on. Mitähän varten tuon kokoisesta tiedostosta pitää jatkuvasti lukea samaa riviä? Mikä sitä muuttaa, olisiko jotenkin mahdollista pitää yhteyttä pienemmillä tiedostoilla tai esimerkiksi piipuilla?

Teen vb.netillä harjoituksen vuoksi semmoisen palvelun joka hakee säätietoja eri sivuilta. Sivu, josta tiedot haetaan haalitaan ensin streamiin, josta luetaan tarvitavat rivit, eli juurikin tuo rivi 113. Palvelun olisi tarkoitus pyöriä windoksessa taustalla ja kirjoittaa säähavaintoja lokiin. Teen siihen vielä lisäksi käyttöliittymän jolla tuota palvelua voidaan ohjata; sulkea, käynnistää, selata tilastoja, lokeja, jne. Käyttäjä voi itse määrätä aikamääreen tuolla käyttäliittymällä säätietojen pollaamiseen. Tuo "tietyin väliajoin" tulee siis tarkoittamaan aikaa väliltä 1min - 24h. Palvelu hakee myös kerran päivässä sääkartan ja viiden vuorokauden ennusteen kuvina tietyilta nettisivuilta.

Tämä on eka vb.net projekti, niin pitää vain koittaa tutustua uusiin ominaisuuksiin, esim. tuohon streamreaderiin.

Harjoittelen vielä tätä .nettiä, mitä siis tarkoitat tuolla, että "olisiko mahdollista pitää yhteyttä pienemmillä tiedostoilla tai esimerkiksi piipuilla?" Mistään piipuista en ole mitään kuullutkaan. VB kutosta olen käyttänyt kovasti, mutten sieltäkään muista mitään näitä piipuista? :)

Metabolix [21.07.2005 18:07:52]

#

Tarkoitin vain, että jos tarkoituksena olisi pitää yhteyttä kahden ohjelman välillä, niin tiedostot eivät kannattaisi. Piippu (pipe) on sellainen hyvin paljon tiedoston tavoin toimiva tiedonsiirtokanava, ja niitä kannattaa usein käyttää, jos pitää kahden ohjelman välillä siirtää tietoa.

Tuollaisessa systeemissä varmaankin kelpaa hyvin tuo StreamReader. (Tuskin tuohon kovin monta muuta tapaa edes on.) Tietenkin jos tiedosto pysyy aina samana johonkin asti, on tehokasta hypätä sinne suorempaa tietä.

' Siirrytään tiedoston kohtaan Tavujen_Määrä
StreamReader_Olio.BaseStream.Seek(Tavujen_Määrä, System.IO.SeekOrigin.Begin)

AM [21.07.2005 18:20:48]

#

Erittäin hyvä neuvo. Sivu jolta säätiedot haen on samanlainen aina tietojen alkamiskohtaan asti. Eli tällä pääsen hyppäämään parsittavan tiedon lähelle ja lukemaan siitä rivit ilman että kahlaan koko streamia alusta läpi. Juurikin jotain tällaista hainkin. Kiitos vaan vastauksista.

esakom [22.07.2005 14:46:14]

#

Et kai kirjoita sitä sää sivua ensin tiedostoon ja siitä muistiin? Kannattanee ottaa se sivulta tuleva tavara pelkästään rammissa (muististreamissa), ja kirjoittaa levylle vain ja ainoastaan lokia?

Mutta varmaan jo olit sen näin tehnytkin =)

AM [22.07.2005 17:25:55]

#

Tälläpä tavalla teen sen nyt. Sama pasteta tänne, kun kerran ei ole kuin harjoitusprojekti. Onpa muuten karmean näköistä koodia :)

Public Shared Function g_strHaeSaatiedot() As String

       ' Funktio mikä hakee ilmatieteenlaitoksen sivuilta säätiedot
       ' parsii hatutu tiedot järkevään muotoon ja palauttaa parsitun,          selkokielisen tuloksen
       ' jatkossa tehdään valinta, että voi valita minkä paikan sää haetaan

       ' luodaan webbiclientti joka hakee sivuilta tauhkan
       ' luodaan steami johon tauhka luetaan
       ' luodaan streamreader
       Dim wWebClient As New WebClient
       Dim sStream As Stream
       Dim srReader As StreamReader
       Dim strParsi As String

       ' muuttujat joihin haetaan kaikki kolme riviä millä säätiedot ovat
       Dim strHavaintoPaikka As String
       Dim strHavaintoAika As String
       Dim strHavaintoTemp As String

       ' parsimista varten omat muuttujat
       Dim strPaikka As String
       Dim strAika As String
       Dim strLampotila As String
       Dim strPaine As String
       Dim strKosteus As String
       Dim strTuuli As String
       Dim strPilevet As String

       Dim i As Integer

       Try
           ' luetaan striimiin ilmatieteenlaitoksen lappeenrannan lähde
           sStream = wWebClient.OpenRead("http://www.ilmatieteenlaitos.             fi/saa/paikalli.html?kunta=Lappeenranta")

           ' alustetaan streamreaderi ja passataan haettu streami                   siihen
           srReader = New StreamReader(sStream)

           ' luetana eka rivi, että ei ois nothing heti silmukan alussa
           strParsi = srReader.ReadLine

           ' pyöritään silmukassa niin kauan että streami on luettu                 läpi
           Do Until strParsi Is Nothing

               ' luetaan rivi ja siirrytään samalla seuraavaan
               strParsi = srReader.ReadLine

               ' kasvatetaan rivilaskuria yhdellä
               i = i + 1

               ' jos rivi on 113, niin luetaan kolme seuraavaa riviä.                  ko. riveill esiintyy kaikki tarvittavat tiedot
               If i = 113 Then
                   strHavaintoPaikka = srReader.ReadLine
                   strHavaintoAika = srReader.ReadLine
                   strHavaintoTemp = srReader.ReadLine

                   ' kaikki tarvittavat on nyt tiedossa
                   exit do
               End If
           Loop

           ' parsitaan tiedot
           strPaikka = (m_strParsiPaikka(strHavaintoPaikka))
           strAika = m_strParsiAika(strHavaintoAika)
           strLampotila = m_strParsiTemp(strHavaintoTemp)
           strPaine = m_strParsiPaine(strHavaintoTemp)
           strKosteus = m_strParsiKosteus(strHavaintoTemp)
           strTuuli = m_strParsiTuuli(strHavaintoTemp)
           strPilevet = m_strParsiPilvet(strHavaintoTemp)

           ' palautetaan parsittu tauhka
           g_strHaeSaatiedot = strPaikka & vbCrLf & strAika & vbCrLf &              strLampotila & vbCrLf & strPaine & vbCrLf & strKosteus &                vbCrLf & strTuuli & vbCrLf & strPilevet

       Catch ex As Exception

           ' ilmotetaan virheestä
           MsgBox("Error: " & ex.Message)
       Finally

           ' tapetaan streami, webclientti ja readeri
           sStream.Close()
           wWebClient.Dispose()
           srReader.Close()
       End Try

   End Function

Eli tuo funktio hakee halutun sivun streamiin ja parsii sen, palauttaa sitten stringin, jossa on parsitut tulokset. Tiedostoon kirjoittaminen tapahtuu vielä myöhemmin. Tuota pitää kyllä parannella vielä todella paljon ennen kuin sen siirtää sinne servicen puolelle. Pitää tehdä tarkistukset, että mitä tehdään jos sääpalvelu ei vastaakaan jne. Tällä hetkellä tuokin funktio on siis vielä sääkikkareeni käyttöliittymän puolella, mutta siirrän sen palveluun kun se on valmis. Sen palvelun on tarkoitus hakea vielä sääkartta ja viiden päivän ennsute kerran päivässä, nekin on jo tehty, mutta samat tarkistukset tulee vielä niihinkin.

Kertokaapa ideoita miten tarkistetaan tuon sivuston tila mistä haetaan tauhka. Eli ensin pitäisi ko. sivu pollata ja katosoa vastaako se. Jos ei vastaa niin odottaa tietty aika ja pollata uudelleen. Liekkö tuolla webclientillä mitään .seek -ominaisuutta joka sitten palauttaisi pollttavan sivun statuksen?

Esakom: eli juurihan niin minä sen olin tehnytkin =)


Sivun alkuun

Vastaus

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

Tietoa sivustosta