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 :)
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.
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?
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ä.
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?
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?
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? :)
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)
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.
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 =)
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 =)
Aihe on jo aika vanha, joten et voi enää vastata siihen.