tags:

views:

4474

answers:

9

I want to open a file for reading, the C++ way. I need to be able to do it for text files, which would involve some sort of read line function, and a way to do it for binary files, which would provide a way to read raw data into a char* buffer.

+9  A: 

C++: Input/Output with files

mreggen
+3  A: 

There are three ways to do this, depending on your needs. You could use the old-school C way and call fopen/fread/fclose, or you could use the C++ fstream facilities (ifstream/ofstream), or if you're using MFC, use the CFile class, which provides functions to accomplish actual file operations.

All of these are suitable for both text and binary, though none have a specific readline functionality. What you'd most likely do instead in that case is use the fstream classes (fstream.h) and use the stream operators (<< and >>) or the read function to read/write blocks of text:

int nsize = 10;
char *somedata;
ifstream myfile;
myfile.open("<path to file>");
myfile.read(somedata,nsize);
myfile.close();

Note that, if you're using Visual Studio 2005 or higher, traditional fstream may not be available (there's a new Microsoft implementation, which is slightly different, but accomplishes the same thing).

DannySmurf
+11  A: 

You need to use an ifstream if you just want to read (use an ofstream to write, or an fstream for both).

To open a file in text mode, do the following:

ifstream in("filename.ext", ios_base::in); // the in flag is optional

To open a file in binary mode, you just need to add the "binary" flag.

ifstream in2("filename2.ext", ios_base::in | ios_base::binary );

Use the ifstream.read() function to read a block of characters (in binary or text mode). Use the getline() function (it's global) to read an entire line.

Derek Park
+1 for noting that the global getline() function is to be used instead of the member function.
mxp
I assume the binary flag is only needed in a windows environment?
rogerdpack
roger, I've never found a case where I needed the binary flag on Windows or Unix. In theory, though, it should be used to avoid any implicit conversions. http://stdcxx.apache.org/doc/stdlibug/30-4.html
Derek Park
A: 

fstream are great but I will go a little deeper and tell you about RAII.

The problem with a classic example is that you are forced to close the file by yourself, meaning that you will have to bend your architecture to this need. RAII makes use of the automatic destructor call in C++ to close the file for you.

Update: seems that std::fstream already implements RAII so the code above is useless. I'll keep it here for posterity and as an example of RAII.

class FileOpener
{
public:
    FileOpener(std::fstream& file, const char* fileName): m_file(file)
    { 
     m_file.open(fileName); 
    }
    ~FileOpeneer()
    { 
     file.close(); 
    }

private:
    std::fstream& m_file;
};

You can now use this class in your code like this:

int nsize = 10;
char *somedata;
ifstream myfile;
FileOpener opener(myfile, "<path to file>");
myfile.read(somedata,nsize);
// myfile is closed automatically when opener destructor is called

Learning how RAII works can save you some headaches and some major memory management bugs.

Vincent Robert
File stream objects get closed in their destructor, therefore this new class is useless.
Flame
+1  A: 

@Danny

All of these are suitable for both text and binary, though none have a specific readline functionality.

The fstream facilities actually do have a getline() function. For reasons I don't understand, it's not part of the ifstream class, so lots of people overlook it. (I overlooked it for the longest time.)

Derek Park
+2  A: 

@Vincent

The problem with a classic example is that you are forced to close the file by yourself, meaning that you will have to bend your architecture to this need. RAII makes use of the automatic destructor call in C++ to close the file for you.

If you declare an fstream on the stack, it will be closed when the destructor is fired. It already implements RAII.

Derek Park
Wow, I forgot about that one, thanks... *shame*
Vincent Robert
A: 

@Derek Park: Thanks for that. I had no idea that a getline function existed.

A: 

Anyone interested in RAII, should check out The Official Resource Management Page by Bartosz Milewski.

titanae
A: 

@Derek Park

If you want to read a line from your file, I would recommend using

istream& getline (istream& is, string& str);

from the <string> header instead of:

istream& istream::getline (char* s, streamsize n);

Flame
That's the one I'd intended to link to in the first place (because it doesn't suck). I've corrected that now. Thanks for the heads up.
Derek Park