[C++] verschillende newlines per bestand

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

  • cenix
  • Registratie: September 2001
  • Laatst online: 17-05 08:56
Ik ben momenteel bezig met het uitlezen van een bestand, in C++.
Ik gebruik fstream voor het lezen c.q. schrijven van m'n data.

Nu is het zo dat er in het bestand afwisselend van newline characters gewisseld wordt.

b.v. regels 1 t/m 10 zijn Windows newlines (\x0D \x0A), regel 11 is een unix newline (\x0A) en regel 12 t/m 14 zijn Mac newlines (\x0D) de rest zijn bijvoorbeeld
weer Windows newlines.
(dit varieert per bestand en per regel)

Ik zie veel oplossingen als (pseudo)
C:
1
2
3
4
5
#ifdef WIN32
  #NEWLINE \x0D\x0A
#ifdef UNIX
  #NEWLINE \x0A
#endif


maar daar heb ik niets aan omdat deze door elkaar gebruikt worden.

Uitlezen en controleren op '\x0D' | '\0x0A' werkt niet want daardoor krijg ik I/O fouten.

Uitlezen en controleren op iedere voorkomende newline is wellicht een optie, maar
doordat je de file (offset) pointer continue moet verplaatsen kost dit performance.

Hoe kan ik op een slimme manier ervoor zorgen dat alle soorten newlines op een correcte manier gelezen en verwerkt worden?

  • BoAC
  • Registratie: Februari 2003
  • Laatst online: 20:42

BoAC

Memento mori

Hoe check je dan nu op newlines? 1 compare meer moet toch geen probleem zijn :?

  • cenix
  • Registratie: September 2001
  • Laatst online: 17-05 08:56
Nu geef ik een .get of .getline waarbij ik op de newlines check

Ik heb momenteel het volgende dat vooralsnog lijkt te werken maar dit moet nog helemaal uitgetest worden.

code:
1
2
3
T.getline(szTemp, sizeof(szTemp), '\x0D');
  if (T.peek() == '\x0A')
    T.ignore(1);

[ Voor 64% gewijzigd door cenix op 08-10-2004 11:56 ]


  • BoAC
  • Registratie: Februari 2003
  • Laatst online: 20:42

BoAC

Memento mori

cenix schreef op 08 oktober 2004 @ 11:52:
Nu geef ik een .get of .getline waarbij ik op de newlines check

Ik heb momenteel het volgende dat vooralsnog lijkt te werken maar dit moet nog helemaal uitgetest worden.

code:
1
2
3
T.getline(szTemp, sizeof(szTemp), '\x0D');
  if (T.peek() == '\x0A')
    T.ignore(1);
Ik zou als delimiter \x0A opgeven en checken of het laatste karakter wat ik heb gekregen een \x0D is ;)

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

cenix schreef op 08 oktober 2004 @ 11:52:
Nu geef ik een .get of .getline waarbij ik op de newlines check

Ik heb momenteel het volgende dat vooralsnog lijkt te werken maar dit moet nog helemaal uitgetest worden.

code:
1
2
3
T.getline(szTemp, sizeof(szTemp), '\x0D');
  if (T.peek() == '\x0A')
    T.ignore(1);
Dit kan niet op deze manier, omdat je op deze manier Unix-newlines niet pikt (je herkent nu alleen Win en Mac newlines). Je zult dus een search moeten doen of je oftewel CR of LF tegenkomt, en dan eventueel aangrenzende CR of LF characters ignoren.

Op BoaC's manier slik je overigens de Mac-newlines niet dus dat schiet ook niet op ;)

[ Voor 7% gewijzigd door curry684 op 08-10-2004 12:09 ]

Professionele website nodig?


  • BoAC
  • Registratie: Februari 2003
  • Laatst online: 20:42

BoAC

Memento mori

curry684 schreef op 08 oktober 2004 @ 12:08:
[...]

Dit kan niet op deze manier, omdat je op deze manier Unix-newlines niet pikt (je herkent nu alleen Win en Mac newlines). Je zult dus een search moeten doen of je oftewel CR of LF tegenkomt, en dan eventueel aangrenzende CR of LF characters ignoren.

Op BoaC's manier slik je overigens de Mac-newlines niet dus dat schiet ook niet op ;)
Maar ik doe nooit wat op de mac en de TS ook niet zoals blijkt op de 'TS' ;)

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

BoAC schreef op 08 oktober 2004 @ 12:49:
[...]

Maar ik doe nooit wat op de mac en de TS ook niet zoals blijkt op de 'TS' ;)
Nu is het zo dat er in het bestand afwisselend van newline characters gewisseld wordt.

b.v. regels 1 t/m 10 zijn Windows newlines (\x0D \x0A), regel 11 is een unix newline (\x0A) en regel 12 t/m 14 zijn Mac newlines (\x0D) de rest zijn bijvoorbeeld
weer Windows newlines.
(dit varieert per bestand en per regel)
:?

Professionele website nodig?


  • BoAC
  • Registratie: Februari 2003
  • Laatst online: 20:42

BoAC

Memento mori

Sorry Had eroverheen gelezen maar het is wel duidelijk volgens mij :> ;)

Heb hetzelfde een keer gehad maar dan lees ik gewoon een heel blok binnen waarover een search wordt gedaan (waarbij ik niet eens aan de Mac dacht ;) ):
code:
1
for (curpos = startpos; data[curpos] != '\n' && data[curpos] != '\r' && curpos < len; curpos++);

[ Voor 41% gewijzigd door BoAC op 08-10-2004 13:20 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dus:
  1. char inlezen
  2. char gelijk aan \n? Dan linux newline en stoppen met lezen
  3. char gelijk aan \r? Dan volgende char peeken, als \n dan windows newline en stoppen met lezen (en ignore (1) aanroepen), anders mac newline en stoppen met lezen
  4. char toevoegen aan string, ga verder met 1

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Afhankelijk van wat er in je bestanden precies staat -- ik neem aan dat die lijnen die je eigenlijk wil inlezen ook nog wel data bevatten in een of ander gekend formaat -- zou je zelfs kunnen overwegen om je bestand te laten parsen in plaats van die code zelf te schrijven. Met (f)lex en yacc heb je in no time een stukje code om bestanden te parsen ongeacht welke newlines er in dat bestand zitten, en het zal nog performant zijn ook. Het is misschien wat overkill in jouw geval ('k weet niet wat je precies wil doen), maar ik wou het toch even melden :)
Ik maak er namelijk graag gebruik van om (redelijk) complexe dingen te parsen. Scheelt me veel tijd, en het is typisch een stuk sneller en beter dan wanneer ik de code zelf zou schrijven :P

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Als ie er alleen lijnen uit wilt halen heeft ie genoeg aan een scanner, en dan is flex een beetje overkill aangezien je toch alleen maar zoekt op \r en \n

Een parser is alleen nuttig als er een geneste en/of repeterende structuur in zit

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • cenix
  • Registratie: September 2001
  • Laatst online: 17-05 08:56
Het bestand is opgebouwd uit objecten, in principe hebben deze objecten een redelijk vaste vorm (dictionary) met een vrije inhoud. Ook de volgorde van objecten verschilt.

Om toch de objecten te kunnen vinden is er een soort cross-reference tabel opgenomen. Nu moet ik deze cross-reference tabel opbouwen en deze objecten uitlezen om informatie te extraheren.

Maar omdat je in het bestandstype dus verschillende newline karakters tegenkomt (en ja, ook door elkaar) moet ik de juiste informatie wel kunnen vinden.

Voor de oplettende lezer en/of kenner, het gaat hier om pdf bestanden.

Ik heb bijna weekend :9 dus het kan even duren voordat ik mij weer laat zien met relevante informatie.

[ Voor 9% gewijzigd door cenix op 08-10-2004 14:37 ]


Verwijderd

cenix schreef op 08 oktober 2004 @ 14:36:
Voor de oplettende lezer en/of kenner, het gaat hier om pdf bestanden.
Daar dacht ik meteen aan toen ik je uitleg hierboven las. En ergens had ik al zo'n gevoel toen ik je topicstart las (al was het daar nog een pure gok). Dat zal wel beroepsmisvorming zijn, want ik heb samen met een paar collega's op het werk een engine geschreven die PDFs kan lezen, bewerken en uitschrijven. Dus ik weet precies hoe PDFs opgebouwd zijn. En uit die ervaring kan ik je maar één advies geven: gebruik (f)lex en yacc, het kan je een zee van tijd besparen!

Als ik tenslotten nog even nieuwsgierig mag zijn: wat wil je precies met PDF gaan doen dat je zelf een PDF parser schrijft? :)

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23:07
Foutloos bestandenmet wisselende regeleindes parsen is sowieso praktisch onmogelij. Hoe weet je dan of je een \r\n moet interpreteren als een enkel DOS-einde of een Mac-einde gevolgd door een UNIX-einde?

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Soultaker schreef op 08 oktober 2004 @ 16:58:
Foutloos bestandenmet wisselende regeleindes parsen is sowieso praktisch onmogelij. Hoe weet je dan of je een \r\n moet interpreteren als een enkel DOS-einde of een Mac-einde gevolgd door een UNIX-einde?
Mwa, een lege regel ignore je toch meestal al.

Verwijderd

Soultaker schreef op 08 oktober 2004 @ 16:58:
Foutloos bestandenmet wisselende regeleindes parsen is sowieso praktisch onmogelij. Hoe weet je dan of je een \r\n moet interpreteren als een enkel DOS-einde of een Mac-einde gevolgd door een UNIX-einde?
Je hebt een punt, maar dat maakt in dit geval (PDF bestanden) niets uit :)

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23:07
Zoijar schreef op 08 oktober 2004 @ 18:04:
Mwa, een lege regel ignore je toch meestal al.
Hangt een beetje van de situatie af. Bij HTML kan je die bijvoorbeeld niet altijd weglaten (in preformatted blocks), maar vaak wel. Als extra lege regels geen probleem zijn kan het veel makkelijker; dan interpreteer je gewoon \r OF \n als regeleinde; dan krijg je in een DOS-geformatteerd bestand dubbel zoveel regels, maar dat maakte dus niet uit.

Het is ook de vraag of je bij een parse error een regelnummer wil geven; zo ja, dan is het wel fijn dat je de regels een beetje zinnig hebt geinterpreteerd.

Verwijderd

Je kunt toch ook gewoon \x0d negeren en alle \x0a's als een newline behandelen, of ben ik nu te simpel bezig?

  • BoAC
  • Registratie: Februari 2003
  • Laatst online: 20:42

BoAC

Memento mori

Verwijderd schreef op 08 oktober 2004 @ 21:03:
Je kunt toch ook gewoon \x0d negeren en alle \x0a's als een newline behandelen, of ben ik nu te simpel bezig?
Zie startpost (Ben ik ook in gestonken ;) ):
b.v. regels 1 t/m 10 zijn Windows newlines (\x0D \x0A), regel 11 is een unix newline (\x0A) en regel 12 t/m 14 zijn Mac newlines (\x0D) de rest zijn bijvoorbeeld
;)

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23:07
Gebruiken die nieuwe Macs (met Mac OS-X) trouwens ook nog van die foute newlines, of is dat tegenwoordig gewoon UNIX-style?

Verwijderd

Soultaker schreef op 09 oktober 2004 @ 17:14:
Gebruiken die nieuwe Macs (met Mac OS-X) trouwens ook nog van die foute newlines, of is dat tegenwoordig gewoon UNIX-style?
MacOS X is wat speciaal in dat opzicht. MacOS X native gebruikt de unix line ending. Maar veel applicaties (typisch GUI based) zijn nog carbon based, en die gebruiken nog de mac line endings.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23:07
Ok; dus aannemen dat bestanden die gemaakt zijn onder Mac OS X UNIX-regeleindes hebben is (nog) niet zinnig.

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

cenix schreef op 08 oktober 2004 @ 11:39:
Hoe kan ik op een slimme manier ervoor zorgen dat alle soorten newlines op een correcte manier gelezen en verwerkt worden?
Door in dit geval geen streams te gebruiken, maar gewoon blokken data in te lezen, en een functie te schrijven die daar regels uit kan halen. Afhankelijk van de streams inplementatie zal d'r misschien wel een oplossing voor dit probleem zijn, maar portable is het dan zowiezo niet.

Verwijderd

igmar schreef op 09 oktober 2004 @ 23:28:
[...]


Door in dit geval geen streams te gebruiken, maar gewoon blokken data in te lezen, en een functie te schrijven die daar regels uit kan halen. Afhankelijk van de streams inplementatie zal d'r misschien wel een oplossing voor dit probleem zijn, maar portable is het dan zowiezo niet.
Het lukt wel met steams, alleen is fstream niet geschikt om deze "bagger" te lezen. Bv met inlezen als binaire stream en vervolgens alle \r om te zetten in \n is de data al geschikt voor fstream. Het syntax-probleem blijft, maar dat blijft sowieso altijd :(. Het is maar 1 luizig wrapper-classje. De vraag is alleen wat de performance is vergeleken met andere oplossingen.

  • cenix
  • Registratie: September 2001
  • Laatst online: 17-05 08:56
@_piranha_: Ik ga ongeveer hetzelfde doen als wat jij dus ook al gegaan hebt.

Ik zal dan toch eens gaan kijken naar f(lex) en yacc (als deze er ook voor win32 zijn) en proberen er iets van te maken. Ik weet niet in hoeverre het bruikbaar is/wordt, maar wellicht heb je nog wat tips.

Ook ga ik ondertussen verder werken aan de applicatie die vooralsnog werkt op bestanden met maar 1 soort newline, dan bouw ik de applicatie later wel om.

Alvast bedankt een ieder, ik heb weer wat materiaal om uit te zoeken en te proberen.

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

cenix schreef op 11 oktober 2004 @ 12:57:
Ik zal dan toch eens gaan kijken naar f(lex) en yacc (als deze er ook voor win32 zijn) en proberen er iets van te maken. Ik weet niet in hoeverre het bruikbaar is/wordt, maar wellicht heb je nog wat tips.
Waarom zo moeilijk ? Gewoon hele blokken inlezen, en daar zelf de regels uit halen. Da's een heel stuk simpeler en sneller als een lexer.

Verwijderd

cenix schreef op 11 oktober 2004 @ 12:57:
Ik zal dan toch eens gaan kijken naar f(lex) en yacc (als deze er ook voor win32 zijn) en proberen er iets van te maken. Ik weet niet in hoeverre het bruikbaar is/wordt, maar wellicht heb je nog wat tips.
Die zijn er ook wel voor win32 hoor. Misschien dat je daar dan even een cygwin voor moet installeren, maar goed. Eenmaal je doorhebt hoe die dingen werken zul je ze met plezier gebruiken :)
Als ik je alvast op weg kan zetten met lex en yacc: howto
Succes!
igmar schreef op 11 oktober 2004 @ 15:16:
Waarom zo moeilijk ? Gewoon hele blokken inlezen, en daar zelf de regels uit halen. Da's een heel stuk simpeler en sneller als een lexer.
Dat durf ik betwijfelen. Lex en yacc zijn zelden overkill. Zelfs zoiets simpel als regeltjes ophalen uit een file gaat heel snel. Op 5 minuten heb je zelf wat geschreven, maar even snel heb je lex/yacc gebruikt (ga ik er wel vanuit dat je er al wat mee vertrouwd bent natuurlijk). De lex/yacc oplossing is zelden trager dan je eigen brouwsels en bevatten typisch een stuk minder bugs. Ok, de hele eenvoudige dingetjes kun je zelf misschien ook wel in één keer goed schrijven, maar als het wat complexer wordt ga je al snel ergens een keertje de mist in is mijn ervaring, en je eigen zooi debuggen kost ook tijd.

In dit geval is het nog erger: hij wil PDF files gaan parsen. En geloof me, daar wil je echt lex/yacc voor gebruiken en niet zelf wat in elkaar prutsen. Als je daar aan twijfelt wil ik altijd de uitdaging aangaan. Ik zal ff een PDF parsen met lex/yacc en jij mag zelf wat schrijven. Naast het feit dat ik drie keer sneller klaar zal zijn dan jou zal mijn lex/yacc oplossing niet trager zijn dan jouw oplossing en zonder twijfel veel minder bugs bevatten dan jouw eerste oplossing.

Waarom zou je trouwens het wiel opnieuw uitvinden? :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

cenix schreef op 11 oktober 2004 @ 12:57:
Ik zal dan toch eens gaan kijken naar f(lex) en yacc (als deze er ook voor win32 zijn) en proberen er iets van te maken. Ik weet niet in hoeverre het bruikbaar is/wordt, maar wellicht heb je nog wat tips.
Ik zou voor flex en bison gaan, dat werkt wat soepeler dan yacc (Check http://gnuwin32.sourceforge.net/ voor windows binaries zonder dat je dat gare cygwin nodig hebt). Aan de andere kant vind ik het echter beide baggerparsergenerators omdat ze C parsers genereren, en geen C++ parsers. Wat dat betreft is ANTLR wel mooi, ik zie dat ze tegenwoordig ook gewoon een binary versie hebben (voorheen had je altijd java nodig :/). Ook is er Elkhound, een GLR parser generator (erg mooi om ambiguheden naderhand op te lossen), alleen daar heb ik tot nu toe alleen een linux source van gevonden

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1