Wolverin Skrevet 8. mai 2004 Del Skrevet 8. mai 2004 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
aadnk Skrevet 8. mai 2004 Del Skrevet 8. mai 2004 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
Wolverin Skrevet 8. mai 2004 Forfatter Del Skrevet 8. mai 2004 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
aadnk Skrevet 8. mai 2004 Del Skrevet 8. mai 2004 (endret) 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 8. mai 2004 av aadnk Lenke til kommentar
Wolverin Skrevet 8. mai 2004 Forfatter Del Skrevet 8. mai 2004 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
Anbefalte innlegg
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 kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå