C/reading specific lines from a text file(CDR File) using C
Expert: Zlatko - 10/10/2010
QuestionQUESTION: I have a CDR file containing call informations of a single day.I have to read the lines with the time given and the timestamp.I know how to open the file using C,but don't know how to read those specific lines and accumulate them.
I am sending some lines from the text file:
Fri Sep 21 00:00:07 2007
Acct-Session-Id = "00015FE8"
Framed-Protocol = PPP
Framed-IP-Address = 203.112.201.209
Connect-Info = "31200/12000 V34+/V42bis/LAPM (24000/12000)"
Acct-Authentic = RADIUS
User-Name = "phpfarm"
Acct-Status-Type = Start
NAS-Port = 26
NAS-Port-Type = Async
Calling-Station-Id = "312852663"
Called-Station-Id = "0101111"
Service-Type = Framed-User
NAS-IP-Address = 203.112.192.134
Acct-Delay-Time = 0
Timestamp = 1190311206
Fri Sep 21 00:00:12 2007
User-Name = "ademlbst"
NAS-IP-Address = 203.112.194.9
NAS-Identifier = "203.112.194.9"
Acct-Status-Type = Stop
Acct-Session-Id = "152111160"
Acct-Delay-Time = 0
Acct-Authentic = RADIUS
Service-Type = Framed-User
NAS-Port-Type = Async
NAS-Port = 2322
Calling-Station-Id = "28157778"
Called-Station-Id = "0101"
Framed-Protocol = PPP
Framed-IP-Address = 203.112.197.146
Acct-Session-Time = 1289
Acct-Terminate-Cause = User-Request
Acct-Input-Octets = 121691
Acct-Output-Octets = 5656409
Acct-Input-Packets = 4330
Acct-Output-Packets = 4474
Timestamp = 1190311212
Fri Sep 21 00:00:25 2007
Acct-Session-Id = "00000588"
Framed-Protocol = PPP
Framed-IP-Address = 203.112.215.231
Acct-Authentic = RADIUS
Acct-Terminate-Cause = Lost-Carrier
Acct-Session-Time = 385
Acct-Input-Octets = 95085
Acct-Output-Octets = 466943
Acct-Input-Packets = 767
Acct-Output-Packets = 661
User-Name = "mbelayet"
Acct-Status-Type = Stop
Calling-Station-Id = "56152232"
Called-Station-Id = "0101111"
NAS-Port = 463
NAS-Port-Type = Async
Connect-Info = "45333/28800 V90/V44/LAPM"
Service-Type = Framed-User
NAS-IP-Address = 203.112.192.198
Acct-Delay-Time = 0
Timestamp = 1190311225
it goes on and on....
need help....
ANSWER: Hello Tana
I am sending you a program which will open the file, and isolate the timestamps. Maybe it will be enough of an example to get you started on processing your CDR file. I have put comments into the code to explain what is going on, but if you have questions about it, please ask. Sometimes working with C strings can be confusing because they use pointers, and it takes a while to get used to them.
The only way to get certain lines form a file is to read all the lines, and pick out the ones you want, and that is what the program does. You can specify one file when running the program from a command line. If you don't specify a file name, the program will ask you for one.
Best regards
Zlatko
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
/* useful macro to check if two strings match, ignoring case */
#define STRING_EQ_I(s1, s2) (stricmp(s1, s2) == 0)
/* This function trims blank characters, including newlines, form the end of a string.
If the string starts with spaces, the function returns the location of the first
non-space character in the string */
char *trimSpaces(char* text)
{
/* trim from end */
char* end = text + strlen(text) - 1;
while(end >= text && isspace(*end))
{
*end = 0;
--end;
}
/* trim from beginning */
while(*text && isspace(*text)) ++text;
return text;
}
int main(int argc, char** argv)
{
/* text is used for user input and for input from file.
It should be long enough to hold a line of the file.
*/
char text[128];
/*
Get the filename from the user if the user did not specify it on the command line
*/
char* filename;
if (argc < 2)
{
printf("Input file name\n");
fgets(text,sizeof(text), stdin);
filename = trimSpaces(text);
}
else
{
filename = argv[1];
}
/* Open the file */
FILE* inFile = fopen(filename, "r");
if (inFile == NULL)
{
printf("Cannot open file '%s' : %s\n", filename, strerror(errno));
}
else
{
/* Read the file line by line */
while (true)
{
fgets(text, sizeof(text), inFile);
if(feof(inFile)) break; /* exit the loop if we have read all the lines */
/* Examine lines containing an equal sign '=' */
char* eqSignPtr = strchr(text, '=');
if (eqSignPtr != NULL)
{
*eqSignPtr = 0;
/*
The text to the left of the equal sign is pointed at by key
The text to the right of the equal sign is pointed at by value
*/
char* key = trimSpaces(text);
char* value = trimSpaces(eqSignPtr + 1);
/* printf("Read <%s> <%s>\n", key, value); */
/* process the timestamp */
if (STRING_EQ_I(key, "timestamp"))
{
long timestamp = atol(value);
printf("Found timestamp of %d\n", timestamp);
}
}
}
/* Close the file when done */
fclose(inFile);
}
}
---------- FOLLOW-UP ----------
QUESTION: hello Zlatko,
Thank u soooo much for ur help....u r simply a genius..... but I have a very low knowledge in programming,but i got into trouble,so have to do this. I undrstood some part of your program but most of was too hard for me to understand.
can you plz just xplain me how to open a text file in C?i want to do a simple program to open the file.thn i will try to find out myself how to print specific lines and work with those lines.
But still thank u soo much for helping.
Tana
ANSWER: Hello Tana.
So you want to figure it out for yourself ? Well, you should be proud of yourself.
Please tell me, were you able to compile and run the last program I sent to you? Sorry, I used the word "true" in the program. That is a C++ word, not a C word. I have removed it in the example below.
Below is the simplest program I can think of to open the file, and print out all the lines. Actually it is just the program I sent earlier, with much taken out.
#include <stdio.h>
#include <stdlib.h>
int main()
{
/* text is used for user input and for input from file.
It should be long enough to hold a line of the file.
*/
char text[128];
/* Open the file called CDR.txt
The file will have to be in the same folder as the program.
*/
FILE* inFile = fopen("CDR.txt", "r");
if (inFile == NULL)
{
printf("Cannot open file\n");
}
else
{
/* Read the file line by line */
while (1)
{
fgets(text, sizeof(text), inFile);
if(feof(inFile)) break; /* exit the loop if we have read all the lines */
printf("Got the line '%s'\n", text);
}
/* Close the file when done */
fclose(inFile);
}
}
---------- FOLLOW-UP ----------
QUESTION: heyyy zlatko....
how r u????the file opening program is running fantastically....i have got a new problem.....its with the same cdr file.....i have to store some of its info in the memory and then make out a histogram graph....how can i do tht....
Regards
Tana
AnswerOctober 11
Tana, it may be a good idea to extract the data you want from CDR with a C program and create a comma separated variable file (also known as a CSV file) which can be read in by Microsoft excel or some other spreadsheet program. Then you can use the spreadsheet program to make a nice histogram. Would that idea work for you ?
Hi Tana.
The CDR file has lines in the form key=value. You need to break the line up into two sections, the key to the left of the '=' character, and the value to the right of the '=' character. To do that you will need to be comfortable with pointers. I'll give you a short description.
The program reads lines and stores them in an array called text. The array is a region of memory and the variable text is actually a pointer to the first byte of the memory. The first step to separating the key from the value is to find the location of the equal sign in the array.
The strchr function will do that for you. It will return a pointer to the byte in memory where the equal sign is. You declare a pointer to a character like this:
char* ptrEqualSign;
Then assign the result of strchr to the pointer;
ptrEqualSign = strchr(text, '=');
The next byte after the equal sign is the first character of the value, so declare a pointer to it as well and make it point to memory location right after the equal sign.
char* ptrValue;
ptrValue = ptrEqualSign + 1;
Next you have to separate the key from the value by overwriting the equal sign with a 0. The 0 byte will end the key part of the text.
*ptrEqualSign = 0;
Read the above line as "The memory pointed at by ptrEqualSign gets 0"
You should now be able to replace the line
printf("Got the line '%s'\n", text);
with
printf("Got the key '%s' and value '%s'\n", text, ptrValue);
There is one more thing to understand. Some lines don't have an equal sign, and I suppose you want to ignore those lines, so it is important to check if ptrEqualSign is NULL. If it is NULL, it means that strchr did not find an equal sign.
You can use my explanation to try and create the program, or you can jump ahead to my solution below. Read it and run it. Sometims running code will help you understand it.
So far we have just isolated the key and the value. Next you must check if the key is the one you are interestd in. Lets say you are interested in the "Timestamp", you have to compare your key against the "Timestamp" string and see if they are equal. You compare strings with the strcmp function. The strcmp function will return 0 when strings are equal.
Here is an example:
if (strcmp(text, "Timestamp") == 0)
{
/* do the processing of the timestamp. */
/* The atoi function takes the text representation of a number
and returns an actual number value that you can do arithmetic
with */
int timestamp = atoi(ptrValue);
}
You can see we are still far from creating a histogram. I can continue explaining things to you step-by-step if you like, but if you are in a hurry, just tell me what data you are looking for and I can put together a program for you. I assume this is not a school project. In any case, it would help me to have more details about which CDR lines you are interestd in.
If all this seems really complicated, well that's because it is. There are a lot of ideas here that a person has to understand and it can be overwhelming. The hardest part for beginners is to imagine the bytes of memory holding data and to imagine pointers pointing to different parts of memory. Please do ask about what you don't understand. If I need to, I'll draw you diagrams.
Best regards
Zlatko
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
/* text is used for user input and for input from file.
It should be long enough to hold a line of the file.
*/
char text[128];
/* Open the file called CDR.txt
The file will have to be in the same folder as the program.
*/
FILE* inFile = fopen("CDR.txt", "r");
if (inFile == NULL)
{
printf("Cannot open file\n");
}
else
{
/* Read the file line by line */
while (1)
{
char* ptrEqualSign;
fgets(text, sizeof(text), inFile);
if(feof(inFile)) break; /* exit the loop if we have read all the lines */
ptrEqualSign = strchr(text, '=');
if (ptrEqualSign != NULL) /* check if '=' was found */
{
char* ptrValue;
ptrValue = ptrEqualSign + 1;
*ptrEqualSign = 0;
printf("Got the key '%s' and value '%s'\n",
text, ptrValue);
}
}
/* Close the file when done */
fclose(inFile);
}
}