Solved

reading text file in c++

Posted on 2007-11-22
30
435 Views
Last Modified: 2008-05-25
Hi,

I have a text file & it is having content as
2|50000|1000|S|Abc|0
I would like to read the above file and assign values to six variables: integer and string.

Here, I am using C++ and solaris is the Operating system.
Please tell me like how to do that in C++?

thanks,
shankarraj
0
Comment
Question by:shankarraj
  • 9
  • 8
  • 7
  • +4
30 Comments
 
LVL 53

Assisted Solution

by:Infinity08
Infinity08 earned 25 total points
Comment Utility
Here's a good introduction to I/O with files in C++ :

        http://www.cplusplus.com/doc/tutorial/files.html


An easy way would be to use getline to read a line from the file :

        http://www.cplusplus.com/reference/string/getline.html

and then use string operations (substr, find) to extract the tokens from the line :

        http://www.cplusplus.com/reference/string/string/find.html
        http://www.cplusplus.com/reference/string/string/substr.html
0
 
LVL 11

Assisted Solution

by:DeepuAbrahamK
DeepuAbrahamK earned 25 total points
Comment Utility
For pipe delimited files
http://www.augustcouncil.com/~tgibson/tutorial/iotips.html
This may as well help you.
Best Regards,
DeepuAbrahamK
0
 
LVL 17

Assisted Solution

by:rstaveley
rstaveley earned 25 total points
Comment Utility
A combination of getline and extraction on an istringstream does the trick nicely with this sort of thing. Experience says don't do it directly with the ifstream, because one bad line thrhows it all out of kilter otherwise.

The not-so-secret weapon here is using '|' as the delimiter to getline.
#include <fstream>

#include <sstream>

#include <iostream>
 

int main()

{

	std::ifstream fin("x.dat");

	std::string str;

	while (getline(fin,str)) {

		std::istringstream istr(str);
 

		// For the likes of "2|50000|1000|S|Abc|0"

		std::string str1,str2;

		int i1,i2,i3,i4;

		char junk;
 

		if (

			(istr >> i1) && (istr >> junk) && (junk == '|')

		&&	(istr >> i2) && (istr >> junk) && (junk == '|')

		&&	(istr >> i3) && (istr >> junk) && (junk == '|')

		&&	getline(istr,str1,'|')

		&&	getline(istr,str2,'|')

		&&	(istr >> i4) /*&& (istr >> junk) && (junk == '|')*/

		) {

			std::cout << i1 << '|' << i2 << '|' << i3 << '|' << str1 << '|' << str2 << '|' << i4 << '\n';

		}

	}

}

Open in new window

0
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 25 total points
Comment Utility
You can read the file with

#include <fstream>
#include <string>
using namespace std;

       

        ifstream  file("file.dat");
        string line;
        while (getline(file, line))
        {
             ...
        }
        file.close();


That reads the file line by line.

For the ...

you should parse the string line like that:

     line += '|';   // add a final delimiter
     int pos = 0;
     int lpos = 0;
     int nitem = 0;
     while ((pos = (int)line.find('|', lpos)) != string::npos)
     {
            string item = line.substr(pos, lpos - pos);
            ...
            nitem++;
            lpos = pos + 1;
     }


Put the following below includes and above all code or in a header file:

#include <sstream>

enum { FLD0, FLD1 , FLD2, FLD3, FLD4, FLD5, FLD_MAX };

struct Record
{
     int ifld0;
     int ifld1;
     int ifld2;
     char cfld3;
     string sfld4;
     int ifld5;
     
};
 
For the ...  you may evaluate the columns like taht:

          Record rec;
          switch(nitem)
          {
              case FLD0:  
              {
                     istringstream iss(item);
                     if (!iss >> rec.ifld0)
                     {
                             cout << "wrong item " << item << endl;
                             return;
                     }
               }
               break;
              case FLD1:  
              {
                     // dito to FLD0
              }
              break;
              ...
              case FLD3:  
              {
                     if (item.length() != 1)
                     {
                             cout << "wrong item " << item << endl;
                             return;
                     }
                     rec.cfld3 = item[i];
               }
               break;
              case FLD4:   rec.sfld4 = item; break;
              case FLD5:  
              {
                     // dito to FLD0
              }
                 
          }
          ...

Finally you  have to store the Record rec to some container and array. I would suggest

   std::vector<Record> records;

Then the ... would be


       records.push_back(rec);


Regards, Alex


         

0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
Heh ... as usual, you're more elaborate in your replies than me, Alex ... ;)
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>>>> you're more elaborate in your replies than me, Alex ...

'elaborate' ??? you mean chatty?

Rob, only needs one third of that I needed ... most likely you'll get the points ... oh the world is bad ...
0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
>> 'elaborate' ??? you mean chatty?

http://www.merriam-webster.com/dictionary/elaborate    ;)

That was a compliment btw !!
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
I like the Latin 'elaboratus'  ;-)

0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
There is nothing wrong with a good chat, lubricated of course by an excellent Belgian beer.

Infinity08, do you get an "Attach beer snippet" checkbox in your locale? 8-)
0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
>> Infinity08, do you get an "Attach beer snippet" checkbox in your locale? 8-)

I wish ... I would probably add a good Rochefort 8 trappist beer (one of my favorite Belgian beers) :) Mmm ... with a bit of cheese on the side, it's just perfect heh
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>>>> by an excellent Belgian beer.
it is 'perfumed', isn't it? Did you never hear of 'beer purity law' ?

BTW, I have draft beer (Philipps system 6 liters, mostly with Becks) in my home bureau. Nearly as good as a checkbox and much more real ;-)  The only problem is that I am 'on the road' from Monday to Thursday ...
0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
>> id you never hear of 'beer purity law' ?

No, but a short look on the internet reveals that the ingredients of beer can only be barley, hops and water. That's quite limiting, and doesn't permit "alive" beer, since you can't use yeast ... it also doesn't include sugar which is commonly used for the "good" beers.

These are the 5 ingredients of a Rochefort trappist beer : water, hops, barley, yeast and sugar.
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
It's liquid bread really. I'll look out for Rochefort. I'm still a Trappist newbie, but eager to learn more.
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
Here's my general solution (religion/culture permitting):
not_so_std::beerstream beer("Rochefort");

while (beer >> rstaveley >> Infinity08 >> itsemeandnobodyelse)

    ;

Open in new window

0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
Hmmm... I think Infinity08 had too much, he got syntax highlighted!
0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
Why do you get served first ? lol

On the upside, my name is in purple ... hehe
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>>>> yeast
Actually there is no beer without yeast. But they didn't mention it in the law (most likely they didn't want to confuse the customers?)

>>>> sugar
Brrrrrrrrr. Didn't I say it it is 'perfumed'. Ever heard that a 'real' man drinks sweet beer?

>>>> Why do you get served first ? lol
You can get my share. I've heard the dregs contain most of the sugar....
0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
>> >>>> sugar
>> Brrrrrrrrr. Didn't I say it it is 'perfumed'. Ever heard that a 'real' man drinks sweet beer?

Oh, but the beer is not sweet. The sugar is converted to alcohol, and is added to have a higher alcohol percentage. The Rochefort 8 I mentioned for example is about 9% alcohol. I've drank beers upto 15% in Belgium.
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
> I've drank beers upto 15% in Belgium.

That's enough to make you go purple.
0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
lol
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
> I've drank beers upto 15% in Belgium.
I've drunk (bock) beer up to 21% ... of course ... no sugar

>>>> That's enough to make you go purple
When lying under the table the colors don't matter ;-)

BTW, I am at home today but I've to wait until noon (f...ing principles) before I get my first beer ...
0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
>> I've drunk (bock) beer up to 21%

Wow ... never heard of a Bock with that much alcohol ... must have been some special brew ...
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
> I've to wait until noon

"I like a good beer buzz early in the morning..." (S. Crow)
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
I think shankarraj has given up on us in despair.
0
 
LVL 40

Accepted Solution

by:
evilrix earned 25 total points
Comment Utility
Fully working example.
//  Required for std::stringstream

#include <sstream>
 

// Required for for_each()

#include <algorithm>
 

// Required for std::istream

#include <iostream>
 

// Required for std::vector

#include <vector>
 

// Data -- POD type (this could also be a proper class!)

struct Data

{

	int field1;

	int field2;

	int field3;

	char field4;

	std::string field5;

	int field6;

};
 

// Overloaded input stream operator

std::istream & operator >> (std::istream & is, Data & data)

{

	std::string line;

	getline(is, line);
 

	if(is.good())

	{

		std::string::size_type pos = 0;

		std::string::size_type lpos = 0;
 

		int const LAST_FIELD = 6;
 

		for(int field = 0 ; field < LAST_FIELD ; ++ field)

		{
 

			// Find end of field

			if(std::string::npos == (pos = line.find('|', lpos)))

			{

				// If not found and last field use size

				if((LAST_FIELD - 1) == field)

				{

					pos = line.size();

				}

				else // If not last field we have an error condition

				{

					throw std::runtime_error("Invalid record structure");

				}

			}
 

			// Use to convert to the required data type

			std::stringstream ssField(line.substr(lpos, (pos - lpos)));
 

			// Start of next field

			lpos = pos + 1;
 

			// Extract field

			switch(field)

			{

			case 0:

				ssField >> data.field1;

				break;

			case 1:

				ssField >> data.field2;

				break;

			case 2:

				ssField >> data.field3;

				break;

			case 3:

				ssField >> data.field4;

				break;

			case 4:

				ssField >> data.field5;

				break;

			case 5:

				ssField >> data.field6;

				break;

			default:

				// We should never get here!

				throw std::runtime_error("Invalid record size");

				break;

			}

		}

	}
 

	return is;

}
 

// Typedef to make code more readable

typedef std::vector<Data> DataVector;
 

// Processes stream and builds a vector of records

void ProcessStream(std::istream & is, DataVector & dv)

{

	for(;;)

	{

		// Create new data structure

		Data data = {0};
 

		// Stream out next record

		is >> data ;
 

		// Process file until EOF or error

		if(is.eof()) { break; }

		if(is.bad()) { throw std::runtime_error("Error. Bad file stream."); }
 

		// Store record in vector

		dv.push_back(data);

	}

}
 

// Output functor (just for demo purposes)

class OutputResult

{

public:

	OutputResult(): m_nRecCnt(0){}

	void operator()(Data const & data)

	{

		++ m_nRecCnt;

		std::cout

			<< "Record: " << m_nRecCnt << std::endl

			<< "- Field1: " << data.field1 << std::endl

			<< "- Field2: " << data.field2 << std::endl

			<< "- Field3: " << data.field3 << std::endl

			<< "- Field4: " << data.field4 << std::endl

			<< "- Field5: " << data.field5 << std::endl

			<< "- Field6: " << data.field6 << std::endl

			<< std::endl;

	}

private:

	int m_nRecCnt;

};
 

int main()

{

	// Test data (this can be from an ifstream -- e.g. ifstream testdata("testdata.txt"))

	std::stringstream testdata (

		"1|50000|1000|S|Abc|0\n"

		"2|50001|1001|T|Def|1\n"

		"3|50002|1002|U|Ghi|2\n"

		"4|50003|1003|V|Jkl|3\n"

		"5|50003|1004|W|Mno|4\n"

		"6|50003|1005|X|Pqr|5\n"

		"7|50003|1006|Y|Stu|6\n"

	);
 

	// Data will be read into this vector

	DataVector dv;
 

	// Process data from stream

	ProcessStream(testdata, dv);
 

	// Output records in vector

	std::for_each(dv.begin(), dv.end(), OutputResult());
 

	return 0;

}

Open in new window

0
 
LVL 40

Expert Comment

by:evilrix
Comment Utility
If you want to catch and explicitly report the thrown exceptions change main to be like this...
int main()

{

	int nRetval = 0;
 

	try

	{

		// Test data (this can be from an ifstream -- e.g. ifstream testdata("testdata.txt"))

		std::stringstream testdata (

			"1|50000|1000|S|Abc|0\n"

			"2|50001|1001|T|Def|1\n"

			"3|50002|1002|U|Ghi|2\n"

			"4|50003|1003|V|Jkl|3\n"

			"5|50003|1004|W|Mno|4\n"

			"6|50003|1005|X|Pqr|5\n"

			"7|50003|1006|Y|Stu|6\n"

		);
 

		// Data will be read into this vector

		DataVector dv;
 

		// Process data from stream

		ProcessStream(testdata, dv);
 

		// Output records in vector

		std::for_each(dv.begin(), dv.end(), OutputResult());

	}

	catch(std::exception const & ex)

	{

		std::cerr << ex.what();

		nRetval = -1;

	}
 

	return nRetval;

}

Open in new window

0
 
LVL 6

Expert Comment

by:SJT2003A
Comment Utility
OK, check the following code. It is a simple example of reading a text file which contains of fields of any type (ie, string, non-string) with | (pipe) delimited.  
The sField is a string stores any type where as nField stores only numberic fields. Just uncomment the commented lines to read from a file.

Check it out. Good luck :)

#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>

using namespace std;

int main()
{
      string line("123|Samson|262|345 Blvd|North York|L9T 5Y3");
      //ifstream ifstr("mydata.dat");
      istringstream istr;
      string alphabetic("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
      string numeric("1234567890");
      string sField;
      long nField;
      string str;
      int pos, lpos;
      //if (!ifstr) {
      //      cout << "file open error " << endl;
      //      exit(1);
      //}

      //while (getline(ifstr,line)) {  //add this line if it is for a file read
            lpos = 0;
            do {
                  pos = line.find_first_of("|",lpos);
                  str = line.substr(lpos, (pos-lpos));
                  if ( (int(str.find_first_of(alphabetic)) >= 0 && int(str.find_first_of(numeric)) >= 0) || //alphanumeric
                        (int(str.find_first_of(alphabetic)) >= 0) ) { //alphabetic
                        sField = str;
                        cout << sField << endl;
                  }
                  else if (int(str.find_first_of(numeric)) >= 0) { //numeric
                        istr.str(str);
                        istr >> nField;
                        cout << nField << endl;
                        istr.clear();
                  }
                  else { //special chars
                        sField = str;
                        cout << sField << endl;
                  }
                  lpos = pos+1;
            } while (pos >= 0);

      //} //while

      return 0;
}

The output is as follows:

123
Samson
262
345 Blvd
North York
L9T 5Y3
Press any key to continue

 
0
 
LVL 6

Expert Comment

by:SeanDurkin
Comment Utility
No comment has been added to this question in more than 21 days, so it is now classified as abandoned.

I will leave the following recommendation for this question in the Cleanup Zone:
      Split: rstaveley {http:#20334000} & Infinity08 {http:#20333741} & DeepuAbrahamK {http:#20333794} & itsmeandnobodyelse {http:#20334030} & evilrix {http:#20345750}

Any objections should be posted here in the next 4 days. After that time, the question will be closed.

Sean
EE Cleanup Volunteer
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now