Using .txt files (C++)

Started by
12 comments, last by Motocrossdoug 17 years, 5 months ago
I was curious as to how I am to use .txt files in C++. For example lets say I would put a bunch of numbers in a text file. And then I wanted the program to load those numbers and display them on screen. Also how would I submit these numbers back to a different text file and save it? For example lets say I get all of those numbers from the other text file, how would I add them to a new text file? (Ideally just creating two of the same txt files) Thanks a lot deadboy
Advertisement

#include <fstream>

You just need to make an ifstream and ofstream using the files you want to copy from and to. Haven't actually done this in a while, so this might be a bit off.

ifstream IN(filename);
ofstream OUT(filename);

That'll creat the streams, from there you just need to make a buffer and copy from file to file. Such as...

int buffer[10];

for(int i=0;i<10;i++) //Get 10 integers (example)
IN >> buffer; //Copy

Same thing with ofstreams, just use << ( OUT << buffer[0] << " " << endl; for example.


Hope that helps

Text files are pretty easy. I'm assuming you know a bit of C++, here, so I'll skip that stuff!

On the basics, you need to learn a form of file opperation. You can use a few methods, two being System::IO:FileStream in the .NET framework, or fstream in 'normal' windows programming. There's tons of info in the MSDN and all, so I'll skip how to use them explicitly (I'll just give an example!) Just keep in mind how you open a file, so you're not erasing the data, and all that.

Besides opening files, and reading from them, you have to remember, if you're reading information from a txt file, the data you're reading from is a string! This means you'll have to parse it as well, you can't just read in integers or bytes and have your numbers. There's also a few ways to do this, and a few functions you can use. Some would be using System::Int32 or what ever type and use the Parse() functions, or using various other parsing methods that escape me at the moment... >.> I'll post 'em if I remember, but either way, it shouldn't be too hard to figgure out off of this.

side note: I did not check if this code works, but I'm 90% sure it does, except for the portion about creating the array for IndexOfAny()... wide character new line and other things escape me, as well...
/* I'll only show ya' the .NET version mostly because those parsingmethods for 'standard' programming escape me! Perhaps someone can fill thispart in? */int ReadNumberFile(System::String ^FileName, int *Numbers)/* file name and pointer to an array that will hold the numbers! We'll returnthe ammount read in, and leave it up to the rest of the program to release thenumbers.The seperate numbers in the file must be seperated by spaces or on a new linefor this to function properly.*/{	System::IO::TextReader ^Reader = gcnew System::IO::StreamReader(FileName);	/* The association between this and FileStream is the stream! If you wanted	to, you could pass a valid FileStream^ to StreamReader(), or you could just	open up a file like this:	System::IO::FileStream ^FS=System::IO::File::Open(FileName,System::IO::FileMode::Open);	and read in the entire file into a char array, and parse it from there...	The only reason I'm using TextReader is it has some nifty functions to make	txt files easy to use!*/	System::String ^TextFile;	TextFile=Reader->ReadToEnd();	Reader->Close();	// if there's nothin' to do, let's get out of here!	if(TextFile->Length==0)		return 0;	// Now we need to find out how many numbers we're dealing with.	// This is just used in the String functions to test against.	array<wchar_t>^chars=gcnew array<wchar_t>(3);	chars[0]=L'/n';	// new line	chars[1]=L' ';	// space	chars[2]=L'/eof';// end of file	int pos=0, pos2=0, num=0, cnum=0; // position in file (two of them), the number of numbers, and one for later (current number).	while(pos<TextFile->Length)	{		pos=TextFile->IndexOfAny(chars,pos);		num++;	}	// now we have our number, let's start parsing for real!	Numbers = new int[num];	// we gotta' make our space.	pos=0;	for(cnum;cnum<num;cnum++)	{		pos2=TextFile->IndexOfAny(chars,pos);			// find the end of our current number		System::String ^Number=TextFile->Substring(pos,pos2-pos);// get our next string		Numbers[cnum]=System::Int32::Parse(Number);		// parse our number		pos=pos2;										// set our indecees so they work for the next loop	}	delete chars; // we have to clean up after ourselves.	return num;}


[Edited by - Motocrossdoug on November 6, 2006 4:12:50 AM]
Thanks for that, though I am not sure I understand everything stated. Is there some other way maybe that you could word the way you explained things?
Hrm... I'll try ta' say it again being more clear...

Besides the basics of C++, for working with files (specifically, txt files), you need to learn about two things.

1. File opperation. You need to learn how a program can access files on the disk. Pretty much, they all have to do with streams. Streams just like the console when you use >> and << to 'push' info onto the screen, but these streams are going out to files. There's several methods you can use to actually put information (and getting info) into the file and all that, but for the most part, I'd sudgest either doing what I said earlier for .NET, or using the ifstream/ofstream/fstream classes. They're all pretty easy to use, you just have to get used to the idea that you're getting information in a linear manner.

2. The second thing, which mostly partains to text, is parsing. The only reason I didn't give an example using fstream is simply that I forgot the functions to use to parse char arrays! >.< Parsing is basically taking text information, and turning it into raw data. For example:

char Text[5]="1264"; // now the string (or char array) Text has 1264 in it.int Number=0;Number=Text;  /* this simply doesn't work, (besides Text itself being a pointer)                because Text has the number in text form, "1264" is four                seperate char's, each containing a number value to represent the                text letter. Text[0]=="1", Text[0]==49, Text[1]=="2"==50, etc.*/Number = ParseIntFromString(Text); /* this does work, because the magical                parsing function will return the actual data number found in                Text, and not simply the number value of each character. */


The bad thing is... I know there's a function that could replace ParseIntFromString(), but I simply forgot what it is! It's a standard string opperation function, much like strcmp() or sprint()... This is going to bug me for a while... I think it may even be a close relative to sprint()... (or String::Format() in .NET, but .NET has all the nifty functions like Int32::Parse()...)


Well, anyways, once you know both of those, you should be just dandy to work with files, and txt files as long as you always keep in mind all those specifics of how you're reading the data in and all that. ^.^
Hm... didn't know << and >> parsed numbers and all... how useful. ~.^

The only problem I see with using this is that it could be difficult to keep track of exactly where you're reading and writing to...

Also, can you use << and >> with raw data like a custom class? or do these opperators only work with asci text?

(as you can tell, I haven't worked much with those opperators and streams... >.>)

edit: well dang, someone had a good example up using ifstream and ofstream. basically it was

// reading inifstream f("File.txt")if(!f.IsOpen()) // may not be the exact funtion, but meh...    // failed to open, deal with itint Num;f>>Num; // read in using the stream opperator >>f.close();// writing outofstream f("File.txt")// same check for opened...int num=20;f<<num;int num2=10, num3=31, num4=40;f<< num2 << " " << num3 << " " << num4;f.close();


Using those opperators in that manner raised my questions...

edit2: mattd, you devil, you. :P
(EDIT: Uh, for some reason I accidentally deleted my earlier post. Here it is again)

These examples are pure C++ - they do not assume you have access to any particular framework or library (other than the SC++L, of course).


Load and print numbers (C++):
#include <fstream>/* ... */// Open the filestd::ifstream f("numbers.txt");if(!f.is_open())    // Failed to open file, deal with it.while(f.good()){    // Read and display a number    int num;    f >> num;    std::cout << "Loaded number: " << num << std::endl;}f.close();



Save numbers (C++):
#include <fstream>/* ... */// Some numbers. You could put these in a std::vector or another container instead.int a = 123, b = 444, c = 678;/* ... */// Open the filestd::ofstream f("numbers.txt");if(!f.is_open())    // Failed to open file, deal with it.// Write the numbersf << a << " " << b << " " << c;f.close();



References:

ifstream
ofstream

You'll note that ifstream / ofstream are just normal C++ streams (like std::cout). You can therefore write and read from files using operator<< and operator>>.
Quote:Original post by Motocrossdoug
Also, can you use << and >> with raw data like a custom class? or do these opperators only work with asci text?


If you want to read into a custom class with >>, you have to provide a function for it.

Say you have a class like:

class Person{public:    Person(){ }    std::string Name; int Age,Weight;};


You can already >> into a std::string and an int, so to be able to >> into a Person, you need to provide an overload function like this:

istream &operator>>(istream &is,Person &p){    return is >> p.Name >> p.Age >> p.Weight;}


which expresses the input in terms of the existing overloads for std::string and int. You could then do:

// person.txt:// Paul 23 16// John 19 8// Claire 18 7void f(){    ifstream is("person.txt");    Person A,B,C;    is >> A >> B >> C;}


much as you would if reading into an int.

What you can't do is use >> to read in raw data from a binary file, or at least not with the standard library streams. For that you need to use the istream::read member function.

All the above applies to writing, but in reverse:

ostream &operator<<(ostream &os,const Person &p){    return os << p.Name << " " << p.Age << " " << p.Weight;}void f(){    Person A,B,C; // fill with data somehow    ofstream os("person.txt");    os << A << endl << B << endl << C << endl;}
Ahh, thought so. Well that's still pretty cool that you can use it to grab text and parse such things... I'd probably recommend against it for a 'real' app, but then if it does what it's supposed to, and does it quickly, who really cares how it works? ^.~
Quote:
I'd probably recommend against it for a 'real' app,

That's silly. There's nothing wrong with them; they're suitable for production use. They're designed for doing "formatted" ("textual") input and output, and for that kind of IO, they're much nicer than the alternatives (in C++; C++/CLI is a different issue being essentially a different language).

The double-duty of the >> and << operators in C++ to mean both shifting and stream extraction or insertion is idiomatic in C++.

This topic is closed to new replies.

Advertisement