Gå til innhold

VB 6.0 program for å lese inn en tekstfil


Anbefalte innlegg

Jeg driver å lager et program som skal lese inn store teksfiler som er semikolon separerte. Filen kan se slik ut:

101;blablabla;blabla;blabla;;;blabla

102;bla;1022;88;XX_XX;120;88

104;800 kr;889

106;0;MVA;trv

199;5

101;tre;ere;rygge;bbb;re5

102;bla;1023;85;XX_X1;102;87

103;Kort;Visa;01

104;1026 kr;860

107;gratis;frakt;0

199;6

999;11

 

Det filen forteller er at recordnr er 3 siffer fremst på hver linje. Hvis den er 101 så er det starten på et sett med records. Settet varer fra 101 til 199, hvor tallet bak 199 representerer antall linjer i settet.

Neders i filen er recordnr 999 som forteller antall linjer av alle recordsett i filen.

Recordnr 102 forteller noe om typen recordsett denne recorden tilhører, og det er da 4 semikolon ut, og en kode på 5 tegn som bestemmer dette.

Hvis koden er XX_XX så skal den i en tekstfil, mens er den XX_X1 så skal den i en annen tekstfil.

Det er altså om å gjøre å flytte linjer fra 101 til 199 til forskjellige filer basert på 102 record sin kode.

Etter dette må programmet holde styr på hvor mange linjer som er blitt flyttet til de ulike filene, dette ved å summere tallet bak 199 recorden, for så å lage en linje med 999;antall_linjer neders i hver av filene som blir laget.

 

Alt ovenfor er ting jeg har gjort, og det fungerer som bare det på små filer, men når filene blir store, så sliter jeg noe veldig.

Hovedløkken min er som følger:

 

open "c:\testfil.txt" for input as #1

do until EOF(1)

kode for å lese ut en og en linje og ta vare på recordnr og noe annet variabel sett

loop

 

På små filer går dette greit. Jeg leser inn en og en linje inn i en variabel av typen String, denne variabelen heter linje hos meg.

Så bryter jeg ned linje med en left(linje,3) for å få ut recordnr på linjen jeg har lest inn.

Hvis recordnr er 102 så kjører jeg en test for om semikolon nummer 4 ut i filen har koden XX_XX eller XX_X1 bak seg. Deretter legges svaret i en variabel.

Så kjører den til recordnr blir 199, også kjører den en

Print #2, recordsett1 eller en Print #3, recordsett2

Dette skriver da recordsett fra 101 til 199 til enten fil 2 eller fil 3.

så tømmes variabelene igjen, og jeg leser inn neste recordsett.

Til slutt skal programmet lage den 999;antall_linjer i hver fil, også Close #2, Close #3.

Problemet jeg får er at på store filer så stenges programmet ned på kriteriet EOF(1) med beskjeden "input line after EOF".

Åssen går det ann da? EOF er vilkåret for å kunne gjøre noe, også klarer programmet på bare store filer å lese etter EOF?

Er det string variablene som skal holde recordsettene som blir for små?

Jeg tenkte kanskje jeg skulle skrive en og en linje til fil, men en Print #2, linje men for hver gang jeg bruker Print #2 så får jeg et entertykk mellom linjene mine da, og det skal det ikke være. Filen skal være tettskrevet slik som eksemplet.

 

Håper noen skjønner noe av dette, og kan gi meg noen tips, for jeg står litt fast nå.

Lenke til kommentar
Videoannonse
Annonse

Jeg er ikke helt sikker på hvordan dette kan oppstå, men kan det være at du har oversett noe? Vel, uansett hva som er årsaken kan jeg ikke gjøre mer uten kildekoden enn å gi et lite tips i OPEN syntaksen:

 

Du kan faktisk skrive til en fil med en og en linje ved å bruke For Binary istedenfor For Output eller For Append. Bruken av denne er beskrevet i dette eksempelet:

 

Dim FilePath As String, Free&, Data(3) As String

FilePath = "C:\testfil.txt"

Data(0) = "hallo"
Data(1) = ";dette"
Data(2) = ";er"
Data(3) = ";en;test"

' For å etterligne Output må du slette filen før bruk:
If Dir(FilePath) <> "" Then
   Kill FilePath
End If

' Ikke nødvendig, men kan forebygge enkelte feil
Free = FreeFile

Open FilePath For Binary As Free
   Put Free, , Data(0)
   Put Free, , Data(1)
   Put Free, , Data(2)
   Put Free, , Data(3)
Close Free

 

I filen C:\testfil.txt vil så denne teksten bli lagret:

 

hallo;dette;er;en;test

 

For å lage linjeskift bruker du kommandoen & Chr(13) i strengen. Som f.eks:

 

Data(2) = ";er" & Chr(13)

 

Hvis du vil kan du jo legge inn hele tekstfilen i en streng, men dette vil jo resultere et enormt bruk av RAM vis filene er veldig store. Uansett, her er koden:

 

Dim FilePath As String, Data As String, Tell&, Lst&

FilePath = "C:\testfil.txt"

' Ikke nødvendig, men kan forebygge enkelte feil
Free = FreeFile

Open FilePath For Binary As Free
   Data = Space(LOF(Free))
   Get Free, , Data
Close Free

' Går så igjennom alle linjer:
Lst = 1

For Tell = 1 To Len(Data)
   If Mid(Data, Tell, 1) = Chr(13) Or Tell = Len(Data) Then
       MsgBox Mid(Data, Lst, Tell - Lst + 1)
       Lst = Tell + 1
   End If
Next

 

Håper dette hjelper.

Lenke til kommentar

Hei.

Er ikke noe i veien for at jeg kan legge ut det jeg har skrevet så langt, men jeg veit ikke om det blir oversiktlig nok, for jeg satt å knota sammen dette sent i går, og har ikke renskrevet noe av koden enda, så variabel navn og utkommenteringer av koden vil prege det hele en smule, men jeg håper likevel det er leselig.

 

 

Private Sub Command1_Click()
Dim linje As String, Tekst As String
Dim teller As Integer
Dim in_path, out_path, out_path2 As String
Dim record, al, tegn, kode As String
Dim antall_linjer, i, lengde, semikolonteller, k As Integer
Dim posisjon As Integer
Dim ant_fil1, ant_fil2, antall_sk As Integer
Dim tekst_fil1, dim_tekst_fil2 As String
Dim vilkar1, vilkar2 As String

in_path = Innfra.Text
out_path = Utfra.Text
out_path2 = Ut2.Text
vilkar1 = recnr.Text
antall_sk = ant_semi.Text
i = 1
k = 0
teller = 0

Open in_path For Input As #1
Open out_path For Output As #2
Open out_path2 For Output As #3

Do Until EOF(1)
Do Until record = 199 
Line Input #1, linje

lengde = Len(linje)
teller = teller + 1
Tekst = Tekst & linje & vbNewLine
record = Left(linje, 3)
If record = "199" Then
al = Mid(linje, 5, 2)
antall_linjer = CInt(al)
'MsgBox "record inneholdt " & antall_linjer & " linjer"
End If

If record = vilkar1 Then 'sjekker om record er vilkår, for så å lete etter semikolon
   Do Until semikolonteller = antall_sk Or k = lengde
   tegn = Mid(linje, i, 1)
   i = i + 1
   k = k + 1
   If tegn = ";" Then
   semikolonteller = semikolonteller + 1
   End If
   'tegn = ""
   Loop
   If k = lengde Then
   MsgBox "det er ikke nok semikolon i filen"
   i = 1
   k = 0
   Else
   'MsgBox "Det er " & k & " tegn til semikolon"
   kode = Mid(linje, i, 5)
   'MsgBox "koden er " & kode
   i = 1
   k = 0
   semikolonteller = 0
   End If
End If
Loop

If kode = "XX_XX" Then
'Print #2, Tekst
tekst_fil1 = tekst_fil1 + Tekst
ant_fil1 = ant_fil1 + antall_linjer 'teller opp antall totale linjer skrevet til fil
Else
'Print #2, Tekst
tekst_fil2 = tekst_fil2 + Tekst
ant_fil2 = ant_fil2 + antall_linjer
End If
record = ""
Tekst = ""
Loop

Close #1 'Lukker input fil lest fra
MsgBox "Det er skrevet " & ant_fil1 & " linjer til fil1"
tekst_fil1 = tekst_fil1 & "999;" & ant_fil1
Print #2, tekst_fil1 'Skriver til fil 1 det som skal til den
Close #2

MsgBox "Det er skrevet " & ant_fil2 & " linjer til fil2"
tekst_fil2 = tekst_fil2 & "999;" & ant_fil2
Print #3, tekst_fil2 'skriv til fil 2 det som skal til den
Close #3
End Sub

 

Håper du kan se feilen for meg, for jeg ser det ikke i alle fall.

Lenke til kommentar

Jeg tror problemet ligger i at du ikke tester for filens ende nok ganger. Se nærmere på denne koden:

 

...
Do Until EOF(1)
Do Until record = 199
Line Input #1, linje
...

 

Her ser du at en intern løkke laster inn data fra filen helt til record 199 ankommer. Men i denne prosessen er det mulig at man har oversteget filens lengde før Record er 199 og feilmeldingen vil anropes. Derfor må du sjekke for EOF før du kjører denne linjen:

 

If Not EOF(1) Then
   Line Input #1, linje

   lengde = Len(linje)
   teller = teller + 1
   Tekst = Tekst & linje & vbNewLine
   record = Left(linje, 3)
Else
   ' Enden av filen er nådd, avslutt innlastingen av recorden.
   record = "199"
End If

 

Håper dette vil fungere.

Ellers kan du naturligvis bare sette en On Error Resume Next på toppen av koden for å ignorere feilene, men jeg vil absolutt ikke anbefale det.

Endret av aadnk
Lenke til kommentar

Du satte meg helt klart på sporet av en løsning her ja.

Det jeg gjorde var å legge til en enkel Or EOF(1) bak testen på 199 record.

Det ble som følger

 

Do Until EOF(1) 'EOF markerer slutt av fil
Do Until record = 199 Or EOF(1) ' EOF markerer slutt av fil
Line Input #1, linje

 

På denne måten sjekker jeg om det er EOF 2 ganger, en gang for hoved loopen som kjører meg gjennom selve program sekvensen min, og en gang pr gang den indre løkken kjøres.

Det fungerte helt yppelig med den test filen jeg hadde på 576 linjer, så jeg skal mekke til en fil som blir betydelig mye større, så får vi se hva den gjør da.

Tusen takk for et puff i rett rettning.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...