Toon posts:

VB6: Bestand regel voor regel lezen

Pagina: 1
Acties:
  • 353 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Ik probeer middels een VB6 programma een bestand regel voor regel te lezen.
Eitje normaal natuurlijk:

Open "eenfile.txt" For Input As nFileNum
Line Input #nFileNum, sNextLine
Close


Dit werkt echter niet op het (ontvangen) EDI bestand.
MSDN leert mij:
The Line Input # statement reads from a file one character at a time until it encounters a carriage return (Chr(13)) or carriage return–linefeed (Chr(13) + Chr(10)) sequence. Carriage return–linefeed sequences are skipped rather than appended to the character string.

Blijkbaar werkt de maker van het bestand niet met een carriage return of carriage return-linefeed. Wanneer ik het bestand echter open met notepad zie ik echter wel dat iedere 'order' op een nieuwe regel begint. Er zal dus toch een soort van regel 'afbreek'-mechanisme aanwezig moeten zijn.

De regels hebben geen vaste lengte, enig idee hoe ik het toch regel voor regel kan uitlezen ?

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Zou je geen While Not Eof(nFileNum) gebruiken dan? :P
De code die je nu post leest 1 regel en sluit het bestand dan weer. Ik zou er een lusje omheen gooien.
En als de records een vaste lengte hebben (wat niet altijd het geval is bij EDI bestanden!) dan kun je ook Get #nFileNum, nRecordNumber, myRecord gebruiken. Zie daarvoor User Defined Types en Get in MSDN.

[ Voor 86% gewijzigd door RobIII op 25-07-2005 12:45 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

Topicstarter
Dat doe ik al, ik loop uiteraar:

Do While Not EOF(nFileNum)
'// Code voor regel te lezen
Loop


Er zijn helaas GEEN vaste regel lengtes

[ Voor 28% gewijzigd door Verwijderd op 25-07-2005 12:46 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Verwijderd schreef op maandag 25 juli 2005 @ 12:44:
Dat doe ik al, ik loop uiteraar:

Do While Not EOF(nFileNum)
'// Code voor regel te lezen
Loop
Post dan je hele code eens?
En wordt er een Cr gebruikt? Of een Lf? Of een CrLf? Open je bestand eens in een Hex-editor? Wat zie je dan? En EDI is nogal een brede standaard (en uit ervaring kan ik je vertellen dat geen hond zich er aan houdt (tenminste, in ons "wereldje" van EDI-slacht)). Welke EDI gaat het hier over?

[ Voor 21% gewijzigd door RobIII op 25-07-2005 12:48 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

Topicstarter
De code is nogal simpel:

Visual Basic:
1
2
3
4
5
6
7
8
nFileNum = FreeFile
Open export_Location & "\" + export_Filename For Input As nFileNum

Do While Not EOF(nFileNum)
     Line Input #nFileNum, sNextLine
Loop

Close nFileNum

Ik zal het bestand even met een Hex editor bekijken.
Bedankt voor de snelle reactie

[ Voor 25% gewijzigd door Verwijderd op 25-07-2005 12:54 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Gebruik [code] tags om code te posten a.u.b. Dat leest prettiger:
Visual Basic:
1
2
3
4
5
6
7
8
nFileNum = FreeFile
Open export_Location & "\" + export_Filename For Input As nFileNum

Do While Not EOF(nFileNum)
   Line Input #nFileNum, sNextLine
Loop

Close nFileNum

[ Voor 8% gewijzigd door RobIII op 25-07-2005 12:49 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

Topicstarter
Hex progje geeft een '0A' aan voor bepalen regel einde.
0A = LF

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Verwijderd schreef op maandag 25 juli 2005 @ 12:53:
Hex progje geeft een '0A' aan voor bepalen regel einde.
0A = LF
En dus geen CrLf.... Dat zou verklaren waarom line input niet werkt. Je zou het eventueel gewoon kunnen inlezen in 1 keer (als de bestanden niet enorm zijn) en dan splitten op LF of, een andere optie zou kunnen zijn met een RegEx het bestand om te gooien zodat er wel CrLf in zit.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • scan
  • Registratie: Augustus 2000
  • Laatst online: 26-10-2025
Misschien dan handiger om het bestand byte voor byte te lezen tot aan een LF ?
Of kan dat niet in Visual basic :P

Een pc is net een brommer. je kan hem wel opvoeren maar het blijft nog steeds een brommer


Verwijderd

Topicstarter
RobIII, het bestand kan wel degelijk groot worden.
LF is afkomstig van Unix (EDI bestand komt uit SAP systeem).
Ik ga proberen het bestand in te lezen, chr$(10) (=LF) te vervangen door vbNewLine.

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Verwijderd schreef op maandag 25 juli 2005 @ 13:02:
RobIII, het bestand kan wel degelijk groot worden.
LF is afkomstig van Unix (EDI bestand komt uit SAP systeem).
Ik ga proberen het bestand in te lezen, chr$(10) (=LF) te vervangen door vbNewLine.
Wat is groot? Onze EDI bestanden zijn meestal niet veel groter dan 10Mb.
Bestanden tot zeg...20 a 30 meg zijn prima in te lezen in redelijke tijd. En anders zou je nog in blokken van X Mb door het bestand kunnen jassen. Een voorbeeldje daarvan heb ik tijden geleden eens gepost. Het doet iets anders, maar je snapt het idee wel: [rml][ vb] Zoeken naar keyword in bestand[/rml] en dan doel ik op deze reply: [rml]RobIII in "[ vb] Zoeken naar keyword in bestand"[/rml]

Als de bestanden dus idd niet al te groot worden dan kun je het in 1 klap inlezen en splitten:
Visual Basic:
1
2
3
4
5
6
7
Dim sMyString as string

FF = FreeFile
Open "C:\blabla" for binary as #FF
sMyString = String(Lof(FF),Chr(0))
Get #FF,,sMyString
Close #FF

Daarna kun je sMyString splitten op een LF.

[ Voor 54% gewijzigd door RobIII op 25-07-2005 13:15 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

Topicstarter
RobIII , bestanden worden denk ik max. 20 MB draaiende op een nauwelijks belaste server met 1024 MB :)
Ik ga de door jou geposte code eens bestuderen aangezien het zeker voldoet aan wat ik nodig heb! Bedankt.

Verwijderd

Alles VBLf vervangen met VBCrLf is niet nodig, je kunt makkelijk het bestand karakter voor karakter doorlezen.

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Dim Karakter As Byte
Dim Regel As String
..
' Open bestand
..
If Not EOF(infile) Then
  Do While True
    Get #infile, , Karakter
    If EOF(infile) Or (Karakter = &HA) Then
      MsgBox (Regel)
      Regel = ""
      If EOF(infile) Then Exit Do
    Else
      Regel = Regel & Chr(Karakter)
    End If
  Loop
End If
..
..


Let wel dat ik deze code zo uit mijn hofd intyp, en er dus nog enig werk nodig is om het geheel werkend te krijgen.

[edit]code gecorrigeerd

[ Voor 14% gewijzigd door Verwijderd op 25-07-2005 13:20 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Verwijderd schreef op maandag 25 juli 2005 @ 13:11:
Alles VBLf vervangen met VBCrLf is niet nodig, je kunt makkelijk het bestand karakter voor karakter doorlezen.

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Dim Karakter As String
Dim Regel As String
..
' Open bestand
..
If Not EOF(infile) Then
  Do While True
    Get #infile, , Karakter
    If EOF(infile) Or (Karakter = vbLf) Then
      ' doe iets met Regel
      Regel = ""
      If EOF(infile) Then Exit Do
    Else
      Regel = Regel & Karakter
    End If
  Loop
End If
..
..


Let wel dat ik deze code zo uit mijn hofd intyp, en er dus nog enig werk nodig is om het geheel werkend te krijgen.
Ja, dat is efficiënt... :X
Op 10 a 20 Mb is dat nogal wat werk, terwijl (zie vorige post) mijn voorbeeld in 1 klap het hele bestand leest. Je kunt dan splitten (desnoods met RegEx, maar je kunt ook de native VB6 Split functie gebruiken) op een LF.
Verwijderd schreef op maandag 25 juli 2005 @ 13:11:
RobIII , bestanden worden denk ik max. 20 MB draaiende op een nauwelijks belaste server met 1024 MB :)
Ik ga de door jou geposte code eens bestuderen aangezien het zeker voldoet aan wat ik nodig heb! Bedankt.
20 Mb moet met mijn voorbeeld hierboven wel lukken, hoewel dat idd niet zo "geheugenvriendelijk" is als lezen in blokken van X Mb's.

Denk er dan aan, dat als je split, dat je dan de originele string weer leeg maakt. Dan geef je effectief dus al meteen weer 20Mb bij. Anders heb je 2x 20Mb in je geheugen zitten: 1 keer als de origineel ingelezen string en 1 keer als Array van strings...

Visual Basic:
1
2
3
4
5
6
Dim myArr() as string

'Hier sMyString inlezen...

myArr() = Split(sMyString, vbLF)
sMyString = "" '<-Hier geef je dus "20Mb" vrij :P

[ Voor 60% gewijzigd door RobIII op 25-07-2005 13:19 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

RobIII schreef op maandag 25 juli 2005 @ 13:13:
[...]
Ja, dat is efficiënt... :X
Ok, niet efficient qua code, maar wel qua geheugengebruik. Ik heb trouwens de code gecorrigeerd.

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Verwijderd schreef op maandag 25 juli 2005 @ 13:20:
[...]

Ok, niet efficient qua code, maar wel qua geheugengebruik. Ik heb trouwens de code gecorrigeerd.
In dit geval weegt het geheugengebruik een stuk minder zwaar. Al was het bestand 1000Mb, dan nog zou je er niet byte voor byte door heen lopen, maar het in blokken van X Mb/Kb lezen. Byte voor byte is nooit een goede oplossing.
En omdat de TS bestanden heeft die "relatief klein" zijn (lees: Ze passen in 1x in een string) kun je dus het bestand ook in 1 klap lezen (hoewel dat minder efficiënt is qua snelheid bij erg grote bestanden, in dat geval moet je dus "blokken" nemen).

[ Voor 25% gewijzigd door RobIII op 25-07-2005 13:27 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

RobIII schreef op maandag 25 juli 2005 @ 13:25:
[...]

In dit geval weegt het geheugengebruik een stuk minder zwaar. Al was het bestand 1000Mb, dan nog zou je er niet byte voor byte door heen lopen, maar het in blokken van X Mb/Kb lezen. Byte voor byte is nooit een goede oplossing.
En omdat de TS bestanden heeft die "relatief klein" zijn (lees: Ze passen in 1x in een string) kun je dus het bestand ook in 1 klap lezen (hoewel dat minder efficiënt is qua snelheid bij erg grote bestanden, in dat geval moet je dus "blokken" nemen).
Point taken :)

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 21:41
Als het comma delimited records zijn oid zou je ook iets met Input# kunnen doen.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
farlane schreef op maandag 25 juli 2005 @ 13:30:
Als het comma delimited records zijn oid zou je ook iets met Input# kunnen doen.
Het zijn EDI bestanden. Die zijn in principe niet "delimited", maar werken op een geheel eigen manier (beetje een voorloper van XML zou je kunnen zeggen). Wel is het zo dat (volgens de standaard) de records worden gescheiden door een Cr of CrLf ofzo (dat zou ik even moeten nakijken).

Zie ook http://en.wikipedia.org/wiki/EDI

Om dan even iets verder in te gaan: EDI bevat "vaste lengte velden". Alleen wordt in het bestand zelf pas beschreven WELKE er aanwezig zijn in het bestand en hoe lang ze dan zijn. Om zaken erger te maken kan halverwege het bestand ook nog eens worden geschakeld naar compleet andere velden:

code:
1
2
3
4
5
6
7
8
9
10
H blablablablabla
V blablablablablabalbalab
V blablablablablabalbalab
V blablablablablabalbalab
H foofoofoofoofoofoofoofoo
V blablablablablabalbalablabla
H brbarbarbarbar
V blablablabla
V blablablabla
V blablablabla

De H regels zijn in dit geval de "Headers" (lees:metadata) waarin staan welke gegevens er volgen, de V regels zijn de "Value" regels, met de eigenlijke waardes.

[ Voor 58% gewijzigd door RobIII op 25-07-2005 13:40 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

Je moet het bestand gewoon binair inlezen en dan eerst een buffer aanmaken in het geheugen en steeds de buffer opnieuw inlezen en verwerken.

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Verwijderd schreef op maandag 25 juli 2005 @ 22:17:
Je moet het bestand gewoon binair inlezen en dan eerst een buffer aanmaken in het geheugen en steeds de buffer opnieuw inlezen en verwerken.
Ja, dat was ondertussen wel duidelijk ;)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 21:41
RobIII schreef op maandag 25 juli 2005 @ 13:32:
Om dan even iets verder in te gaan: EDI bevat "vaste lengte velden". Alleen wordt in het bestand zelf pas beschreven WELKE er aanwezig zijn in het bestand en hoe lang ze dan zijn.
Ah ok. Maar misschien is het in het geval van de TS wel een vast format?
Of moet er algemene EDI importfunctionaliteit komen? Misschien dat je dan beter kunt kijken naar componentjes die te krijgen zijn want het klinkt alsof je dit niet een twee drie in elkaar flanst :)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
farlane schreef op dinsdag 26 juli 2005 @ 11:35:
[...]


Ah ok. Maar misschien is het in het geval van de TS wel een vast format?
Of moet er algemene EDI importfunctionaliteit komen? Misschien dat je dan beter kunt kijken naar componentjes die te krijgen zijn want het klinkt alsof je dit niet een twee drie in elkaar flanst :)
Een EDI bestand inlezen stelt an sich geen fluit voor. Ik heb het wel eens gedaan in een paar regels code in VB6. Het bestand interpreteren is echter wel vaak een crime... Ik heb nooit iets met EDIFact gedaan (de "financiële" EDI bestanden dus); wij werken hier met EDISlacht (EDI slachtinfo bestanden voor geslachtte varkens etc).

[ Voor 4% gewijzigd door RobIII op 26-07-2005 11:52 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 21:41
RobIII schreef op dinsdag 26 juli 2005 @ 11:41:
Een EDI bestand inlezen stelt an sich geen fluit voor. Ik heb het wel eens gedaan in een paar regels code in VB6. Het bestand interpreteren is echter wel vaak een crime.
Das ook wat ik bedoel. Maar als je die Input# kunt gebruiken heb je ook een groot deel van die interpretatie gedaan :)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Pagina: 1