Hulp bij omzetten logdata bestand naar in EXCEL leesbaar bestand.

Status
Niet open voor verdere reacties.

turbofizzl

Gebruiker
Lid geworden
13 aug 2009
Berichten
5
Beste mensen,

Ik ben nieuw hier dus allereerst iedereen de groeten en leuk te zien dat er nog meer tobbers zijn als ik.:shocked:

Ik ben een redelijke noob (groentje) met C programeren en ben bezig met een opdracht om een log bestand van de Vector CANoe om te zetten in een in EXCEL importeerdbare .txt file.

Wellicht zegt een Vector CANoe jullie niks maar dit is een aparaatje waarmee je een CAN-bus zogezegd kan afluisteren en de berichten kan loggen.

Deze gelogde data wordt in een .txt file als volgt opgeslagen:
Code:
date Tue May 26 03:12:51 pm 2009
base hex  timestamps absolute
no internal events logged
// version 7.0.0
   0.000000    EnvGearDown  := 1
   0.000000    EnvGearDown  := 0
   0.000000    EnvGearDown  := 1
   0.000000    EnvGearDown  := 0
   0.000000    EnvGearDown  := 1
   0.000000    EnvGearDown  := 0
   0.000000    EnvGearDown  := 1
   0.000000    EnvGearDown  := 0
   0.000000    EnvGearDown  := 1
   0.000000    EnvGearDown  := 0
   0.000000    EnvGwSwitchIgnition := 2
   0.000000    EnvGwSwitchIgnition := 0
   2.000000    EnvGwSwitchIgnition := 1
   3.000000    EnvGwSwitchIgnition := 2
   3.100158 1  110             Tx   d 3 02 00 00
   3.100158    EnvDashboardEngESPDsp_ := 1
   3.100158    EnvDashboardEngABSDsp_ := 1
   3.100158    EnvDashboardEngOilDsp_ := 1
   3.100158    EnvDashboardEngWaterDsp_ := 1
   3.100158    EnvDashboardEngBaterryDsp_ := 1
   3.100158    EnvBusCommActiveDsp := 1
   3.120180 1  1A0             Tx   d 4 00 00 00 00
   3.120300 1  1F0             Tx   d 1 00
   3.120416 1  1F1             Tx   d 1 00
   3.140180 1  1A0             Tx   d 4 00 00 00 00
   3.150120 1  1F0             Tx   d 1 00
   3.150236 1  1F1             Tx   d 1 00
   3.160180 1  1A0             Tx   d 4 00 00 00 00
   3.180180 1  1A0             Tx   d 4 00 00 00 00
   3.180300 1  1F0             Tx   d 1 00
   3.180416 1  1F1             Tx   d 1 00
   3.200158 1  110             Tx   d 3 02 00 00
   3.200338 1  1A0             Tx   d 4 00 00 00 00
   3.205529 1  41A             Tx   d 4 1A 01 01 FF
   3.205529    EnvNMReceiver26 := 1a
   3.205529    EnvNMStatusDsp26 := 1
   3.210120 1  1F0             Tx   d 1 00
   3.210236 1  1F1             Tx   d 1 00

Nu is mijn taak om dit bestand om te zetten naar een .txt bestand welke in rijen en colommen is gerangschikt volgens het volgende idee:
Code:
time	id	dlc	byte0	byte1	byte2	byte3	byte4	byte5	byte6	byte7
3.100158	110	3	02	00	00
3.120180	1A0	4	00	00	00	00
3.120300	1F0	1	00
3.120416	1F1	1	00
3.140180	1A0	4	00	00	00	00
3.150120	1F0	1	00
3.150236	1F1	1	00
3.160180	1A0	4	00	00	00	00
3.180180	1A0	4	00	00	00	00
3.180300	1F0	1	00
3.180416	1F1	1	00
3.200158	110	3	02	00	00
3.200338	1A0	4	00	00	00	00
3.205529	41A	4	1A	01	01	FF
3.210120	1F0	1	00
3.210236	1F1	1	00
Zoals zichtbaar is zal ik de rijen waar Tx in voorkomt moeten "selecteren" en deze weg moeten schrijven in de gewenste kolommen in het nieuwe bestand.

Het openen en wegschrijven lukt wel maar ik krijg met geen mogelijkheid de juiste waardes in het nieuwe bestand.

Dit is de Code die ik nu heb gemaakt (even in kladblok zetten om et leesbaar te maken denk ik):
[cpp]
#include <stdio.h>
/* #include <conio.h> */

int main(void)
{
FILE *fpin, *fpout;
char flin[256],flout[256];

char rel,x; /* relavant data and new line variables */
signed char meetdata[13]; /* array for logdata */


/* clrscr; */ /* clear screen */
printf("This program converts standard Vector CANoe log files to Ecxel readable files\n\nPlease specify source filename:"); /* print programheader with programfunction and ask for input filename */
scanf("%s",flin); /* read input filename */

/* does inputfile exist ? */

if ((fpin = fopen(flin, "r"))== NULL)
{
printf("Cannot open source file!\n"); /* if not, show cannot open input */
return 1;
}

/* if inputfile does exist */

else
{
printf("Please specify destination filename:"); /* ask to specify destination filename */
scanf("%s",flout); /* read output filename */
fpout = fopen(flout, "w"); /* open outputfile */
x=0; /* select first line of logdata */
}

while((rel=fgetc(fpin))!=EOF) /* while relavant databyte = byte from inputfile and not end of file */
{
if (meetdata[3]=='Tx') /* if logdata colum 2 is 1 (synch) */
{
meetdata[x]=rel; /* logdata[x] is relavant databyte */
x++; /* select new line of logdata */
}
/* write in outputfile */
fprintf(fpout,"%f\t%X\t%d\t%X\t%X\t%X\t%X\t%X\t%X\t%X\t%X\n",meetdata[0],meetdata[2],meetdata[5],meetdata[6],meetdata[7],meetdata[8],meetdata[9],meetdata[10],meetdata[11],meetdata[12],meetdata[13]);
}
/* time\tid\tdlc\tbyte0\tbyte1\tbyte2\tbyte3\tbyte4\tbyte5\tbyte6\tbyte7\n */

fclose(fpin); /* close inputfile */
fclose(fpout); /* close outputfile */
return 0;

}

/*end of main*/
[/cpp]
Ik moet deze opdracht zeer binnenkort af hebben, maar kom er echt niet meer uit!!!
Mijn leraar is al ruim een maand en voorlopig nog zoiets niet bereikbaar vanwegen de vakantieperiode dus daar heb ik ook niets aan.

Please kan iemand mij helpen?:(:(

Alvast erg bedankt.
 
Laatst bewerkt door een moderator:
Je leest het bestand byte voor byte uit met fgetc().
Een regel uitlezen met fgets() (als de regel een maximale lengte heeft).
of gebruik maken van "formatted input" met fscanf() is denk ik handiger.
Overigens geeft fgetc() een int terug dus dan zou het int rel; moeten zijn en niet char rel;

Wat wil je hiermee?
if (meetdata[3]=='Tx') /* if logdata colum 2 is 1 (synch) */

-meetdata[3] heeft geen beginwaarde
-en tussen single quotes '' kan maar 1 karakter staan (en dus niet 2, T en x).
Het commentaar suggereert dat de tweede kolom 1 zou moeten zijn voor de if().
De code zelf suggereert dat de vierde kolom de tekst Tx zou moeten zijn voor de if().

Hiermee:
fprintf(fpout,"%f\t%X\t%d\t%X\t%X\t%X\t%X\t%X\t%X\t%X\t%X\n",meetdata[0],meetdata[2],meetdata[5],meetdata[6],meetdata[7],meetdata[8],meetdata[9],meetdata[10],meetdata[11],meetdata[12],meetdata[13]);
schrijf je een aantal keer 1 karakter als hex weg.
Dat is waarschijnlijk niet wat je wilt.
Probeer elk element in een string te zetten en niet in een karakter dat past namelijk niet altijd.
Bij de laatste 7 kan je het evt. wel doen.
Hoop dat je hier wat mee kan...
 
Laatst bewerkt:
Hoi C er inmiddels begrijp ik dat ik het mezelf moeilijk maak als ik 'Tx' gebruik om de regels te selecteren.

Ik heb er niet bij stil gestaan dat ik het bestand byte voor byte uit aan het lezen ben en dat Tx daarom nu niet werkt.

Ik moet even kijken of de functies die je aangeeft in mijn Dictaat terug komen maar ik heb ze nog niet gebruikt. Het zou met de lesstof in het achterhoofd ook gewoon met fgetc() moeten lukken, al is dit mischien niet de mooiste oplossing.

Wat wil je hiermee?
if (meetdata[3]=='Tx') /* if logdata colum 2 is 1 (synch) */

Met deze Code wilde ik aflopen of de regel Tx bevat zodat ik weet dat deze in de Outputfile terug moet komen.

Ik heb hier een fout laten staan in de Code.:confused:

Ik heb een aantal dingen geprobeerd om de juiste regels te selecteren en naar mijn idee heb ik twee opties.

In de regels waar Tx in terug komt komt in de tweede kolom ook steeds een 1 terug.

Deze 1 kan ik dus ook gebruiken als houvast voor de juiste regels.

Het commentaar had ik dus nog laten staan van de vorige poging:eek:

Verder begrijp ik dat ik beter niet per character kan wegschrijven, maar de hele inhoud van een regel en kolom tegelijk maar hoe doe ik dat?
 
Probeer voor elke regel de elementen in te lezen in een aparte variabele bijv. een char array (dit kan inderdaad ook met fgetc()).
Dus bijv eerst 3.000000 en dan
EnvGwSwitchIgnition enz
Daarna selecteer je op de ingelezen waarden.

Ik zal later wat code posten waar je dan naar kan kijken.

EDIT: wat code die het grotendeels doet, enige aanpassingen zullen wel nodig zijn...
Code:
#include <stdio.h>


void
leesbytes(char bytes[], FILE *fpin)
{
 int i=0;
 int c;

 //spaties overslaan
 do c = fgetc(fpin);
 while( c==' ' );

 while( i<64 && c!=EOF && c!='\n' )
 {
    bytes[i]=c;
    i++;
    c = fgetc(fpin);
 }
 bytes[i]=0;
}



int
leesveld(char veld[], FILE *fpin)
{
 int i=0;
 int c;

 //spaties overslaan
 do c = fgetc(fpin);
 while( c==' ' );

 //in lezen tot een spatie of newline of einde bestand
 while( i<32 && c!=EOF && c!='\n' && c!=' ')
 {
    veld[i]=c;
    i++;
    c = fgetc(fpin);
 }
 //einde streng met NUL
 veld[i]=0;
 return c;
}



int main(void)
{
FILE *fpin, *fpout;
char flin[256],flout[256];

int rel;

char tijd[32],id[32],dlc[32],bytes[128];
char kolom2[32],Tx[32],kolom6[32];


printf("This program converts standard Vector CANoe log files to Ecxel readable files\n\nPlease specify source filename:"); /* print programheader with programfunction and ask for input filename */
scanf("%s",flin); /* read input filename */

/* does inputfile exist ? */
if ((fpin = fopen(flin, "r"))== NULL)
{
printf("Cannot open source file <%s>!\n",flin); /* if not, show cannot open input */
return 1; 
}

/* if inputfile does exist */
else
{
printf("Please specify destination filename:"); /* ask to specify destination filename */
scanf("%s",flout); /* read output filename */
fpout = fopen(flout, "w"); /* open outputfile */
}

if( fpout==NULL )
{
printf("Cannot open Destination file <%s>\n",flout); /* if not, show cannot open output */
return 1;
}

rel = 0;
while( rel!=EOF )// lezen tot een EOF
{
 rel = leesveld(tijd, fpin);
 if( rel != '\n' )
 {
    rel = leesveld(kolom2, fpin);
    if( rel != '\n' )
    {
        rel = leesveld(id, fpin);
        if( rel != '\n' )
        {
            rel = leesveld(Tx, fpin);
            if( rel != '\n' )
            {
                if( strcmp( Tx, "Tx")==0 )//als het 5de veld Tx is
                {
                    leesveld(kolom6, fpin);
                    leesbytes(bytes, fpin);
                    printf("%s %s %s\n",
                    tijd, id, bytes);
                }
            }
        }
    }
 }


}//einde while, einde bestand

fclose(fpin); /* close inputfile */
fclose(fpout); /* close outputfile */
return 0;

}
 
Laatst bewerkt:
C er,

Echt Mega bedankt vast!!!!:thumb:

Ik ga er morgen(eigenlijk al vandaag:shocked:) ochtend even mee aan de slag om te kijken of ik het geheel compleet kan maken en de opdracht ermee kan vervullen.

Als ik nog tegen problemen aanloop zou ik graag nog van je hulp gebruik maken:eek:

Ik moet deze opdracht namelijk afronden voordat ik EINDELIJK op vakantie kan, dus je snapt het wel.

Nogmaals echt mega bedankt vast.
 
Op dit moment ben ik al een heel stuk verder gekomen alleen zijn er nog twee probleempjes.

Ik heb mijn Code nog een stuk aangepast en de uitkomst van de Conversie is bijna wat hij zijn moet.:shocked:

Echter moeten de databytes nog gescheiden worden met tabs en klopt de inhoud van de Data Legth Code (dlc) Array nog niet.

Deze vertoond namelijk een gelijke inhoud als id terwijl de het eerste teken van de Bytes Array steeds gelijk is aan wat de dlc Array zou moeten zijn.

Ik moet dus op de een of andere manier het eerste teken van de Bytes Array appart zien weg te schrijven in de dlc Array ipv de inhoud die er nu in komt.

Maar hoe????:confused:

Verder moet ik de Inhoud van de Bytes Array zien te scheiden mbv tabs zodat deze in EXCEL in andere kolommen terecht komt.

Het moet er dus zo uit komen te zien:

time[tab]id[tab]dlc[tab]byte0[tab]byte1[tab]byte2[tab]byte3[tab]byte4[tab]byte5[tab]byte6[tab]byte7

Hierin is de inhoud dus als volgt:

 Time absolute tijd waarop het CAN bericht is ontvangen.
 ID 11-bits identifier van het CAN bericht (hexadecimaal)
 Length aantal data bytes in het CAN bericht (decimaal)
 ByteX Byte waarde van de desbetreffende byte in het CAN-bericht (hexadecimaal)

Ik heb hiervoor al van alles geprobeert maar ik krijg hierdoor alleen maar foutmeldingen:(

Help, Help, Help!!!

Dit is mijn programmacode nu:

(ik heb hierin dlc even weggelaten in het wegschrijven naar de file omdat er anders dubbele gegevens in komen)

code[]

#include <stdio.h>


void
leesbytes(char bytes[], FILE *fpin)
{
int i=0;
int c;

//spaties overslaan
do c = fgetc(fpin);
while( c==' ' );

while( i<64 && c!=EOF && c!='\n' )
{
bytes=c;
i++;
c = fgetc(fpin);
}
bytes=0;
}



int
leesveld(char veld[], FILE *fpin)
{
int i=0;
int c;

//spaties overslaan
do c = fgetc(fpin);
while( c==' ' );

//in lezen tot een spatie of newline of einde bestand
while( i<32 && c!=EOF && c!='\n' && c!=' ')
{
veld=c;
i++;
c = fgetc(fpin);
}
//einde streng met NUL
veld=0;
return c;
}



int main(void)
{
FILE *fpin, *fpout;
char flin[256],flout[256];

int rel;

char tijd[32],id[32],dlc[32],bytes[128];
char kolom2[32],Tx[32],kolom6[32];


printf("This program converts standard Vector CANoe log files to Ecxel readable files\n\nPlease specify source filename:"); /* print programheader with programfunction and ask for input filename */
scanf("%s",flin); /* read input filename */

/* does inputfile exist ? */
if ((fpin = fopen(flin, "r"))== NULL)
{
printf("Cannot open source file <%s>!\n",flin); /* if not, show cannot open input */
return 1;
}

/* if inputfile does exist */
else
{
printf("Please specify destination filename:"); /* ask to specify destination filename */
scanf("%s",flout); /* read output filename */
fpout = fopen(flout, "w"); /* open outputfile */
fprintf(fpout,"time\tid\tdlc\tbyte0\tbyte1\tbyte2\tbyte3\tbyte4\tbyte5\tbyte6\tbyte7\n");
}

if( fpout==NULL )
{
printf("Cannot open Destination file <%s>\n",flout); /* if not, show cannot open output */
return 1;
}


rel = 0;
while( rel!=EOF )// lezen tot een EOF
{
rel = leesveld(tijd, fpin);
if( rel != '\n' )
{
rel = leesveld(kolom2, fpin);
if( rel != '\n' )
{
rel = leesveld(id, fpin);
if( rel != '\n' )
{
rel = leesveld(Tx, fpin);
if( rel != '\n' )
{
if( strcmp( Tx, "Tx")==0 )//als het 5de veld Tx is
{
leesveld(kolom6, fpin);
leesbytes(bytes, fpin);

fprintf(fpout,"%s\t%s\t%s\n",tijd,id,bytes);
}
}
}
}
}


}//einde while, einde bestand

fclose(fpin); /* close inputfile */
fclose(fpout); /* close outputfile */
return 0;

}

code/[]

Hierbij is nu de uitkomst:

code[]

time id dlc byte0 byte1 byte2 byte3 byte4 byte5 byte6 byte7
3.100158 110 3 02 00 00
3.120180 1A0 4 00 00 00 00
3.120300 1F0 1 00
3.120416 1F1 1 00
3.140180 1A0 4 00 00 00 00
3.150120 1F0 1 00
3.150236 1F1 1 00
3.160180 1A0 4 00 00 00 00
3.180180 1A0 4 00 00 00 00
3.180300 1F0 1 00
3.180416 1F1 1 00
3.200158 110 3 02 00 00
3.200338 1A0 4 00 00 00 00
3.205529 41A 4 1A 01 01 FF
3.210120 1F0 1 00
3.210236 1F1 1 00

code/[]

Waar nu na de id kolom de spaties staan moeten dus eigenlijk tabs komen.

Dan staan alle gegevens in een apparte kolom.

Ik hoop dat er nog iemand mij kan helpen want ik ben zo dicht bij mijn einddoel maar ik kom er echt even niet uit.

Die lonkende vakantie speeld eigenlijk ook niet mee.

Ik zou als het hier niet aan lag immer vandaag al vertrekken :(
 
Het probleem zit hem er in dat je de array genaamd bytes afdrukt als string, en deze dus niet opgeslagen is op de manier waarop jij hem zou willen afdrukken.

Je moet er dus voor zorgen dat hetgeen je afdrukt wel voldoet aan je eisen. Je zou bijvoorbeeld een functie kunnen schrijven die de data in de array bytes omzet naar hetgeen je nodig hebt en deze data vervolgens printen. Iets als onderstaande bijvoorbeeld:

Code:
void convertBytes(char *d, const char *b){
     char buf[512];
     int i,n;
     for(i = 0; i < strlen(b); i++)
         n = sprintf(&buf[strlen(buf)], "%c\t", b[i]);
     memcpy(d, buf, strlen(buf)+1);
}
 
CoD_NL

Kun je de Code die je opgeeft wat verder toelichten?

Ik begrijp wat je ermee wilt bereiken maar niet exact wat of hoe je het doet.

Verder, kan ik het niet in eerste instantie meteen in de juiste vorm zetten?

Dit lijkt mij alsof ik dubbel werk doe omdat ik in de eerste instantie al niet aanmaak wat ik zou willen klopt dat?

En hoe los ik het probleem met de inhoud van de dlc array op?

De eerste karakters die nu uit de bytes array te voorschijn komen moeten in de dlc array staan.

Of anders gezegd dat zijn de Data Legth Code (dlc) gegevens.

I'm so close and yet so far.:confused:
 
CoD_NL
Verder, kan ik het niet in eerste instantie meteen in de juiste vorm zetten?

Ja, het is uiteraard mogelijk om ervoor te zorgen dat de data meteen in de juiste vorm wordt gezet. Je moet dan alleen de grootte van de buffers aanpassen, en in plaats van elke byte achter elkaar te plaatsen na elke byte een aantal spaties te plaatsen wat overeenkomt met het plaatsen van een tab.

En hoe los ik het probleem met de inhoud van de dlc array op?

De eerste karakters die nu uit de bytes array te voorschijn komen moeten in de dlc array staan.

Of anders gezegd dat zijn de Data Legth Code (dlc) gegevens.

I'm so close and yet so far.:confused:

Ik heb nu niet echt de tijd om goed naar je code te kijken, maar je zou met str(n)cpy de waardes kunnen verkrijgen zoals je die zou willen. (al gaat er nu dus iets 'mis' tijdens het inlezen, aangezien bytes een waarde krijgt die niet voor hem bedoeld is, en is het dus netter om het inlezen zelf een klein beetje aan te passen zodat eerst dld gevuld wordt met de juiste waarde. Maar aangezien het huiswerk is mag je hier ook wel zelf nog even mee stoeien :p)
 
Echter moeten de databytes nog gescheiden worden met tabs en klopt de inhoud van de Data Legth Code (dlc) Array nog niet.

Deze vertoond namelijk een gelijke inhoud als id
Dit komt waarschijnlijk omdat je het .txt bestand met iets als kladblok bekijkt. Dit heeft te maken met de werking van tabs.
Excel zal de kolommen wel goed scheiden, probeer het maar eens.
Om het zonder veel wijzigingen in je code het ook in kladblok wat mooier uitgelijnd te krijgen is door:
Code:
fprintf(fpout,"time\tid\tdlc\tbyte0\tbyte1\tbyte2\tbyte3\tbyte4\tbyte5\tbyte6\tbyte7\n");
te vervangen met:
Code:
fprintf(fpout,"time    \tid\tdlc\tbyte0\tbyte1\tbyte2\tbyte3\tbyte4\tbyte5\tbyte6\tbyte7\n");
Hierdoor komt de tekst id wat meer naar rechts, op de volgende tab positie.


Ik moet dus op de een of andere manier het eerste teken van de Bytes Array appart zien weg te schrijven in de dlc Array ipv de inhoud die er nu in komt.

Voor het apart in lezen van een veld had ik dus om je op weg te helpen de functie leesveld() gemaakt.
De functie leesbytes() leest zowel de dlc als de data-bytes in, deze wil je dus niet gebruiken of evt. na een aanpassing.

Als je de dlc en de bytes apart wil moet je ze apart inlezen. D.w.z. dlc in een aparte variable.
Voor de dlc kan je heel makkelijk leesveld() gebruiken.

Daarna moet je de bytes inlezen. Dit is iets lastiger omdat het geen vast aantal is.
-Je kan hierbij veld voor veld met leesveld() inlezen tot het einde van de regel.
-of je kan de waarde van dlc gebruiken, maar dan moet je wel de char array naar een
int converteren met bijv.: atoi(), sscanf() of daar zelf een functie voorschrijven
de waarde kan je ook meteen inlezen als int met fscanf().
je leest daarna dlc keer een veld.
 
Laatst bewerkt:
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan