files in c/c++

Started by
11 comments, last by load_bitmap_file 17 years, 6 months ago
hi, In C you open files to read and write using functions in stdio.h. In c++ you use the streams instead for file operations. What is the difference between the 2 methods as they both appear to do the same thing, so why did c++ reinvent file operations?
Advertisement
Streams are adapted to C++'s object-oriented approach. In particular, polymorphism allows them to be extended globally instead of individually. Using C, and typedef struct { float x; float y; } complex;, write a single function to write a complex in text form to:
- the standard output, error output, or log
- a file
- another string
- any kind of equivalent object, passed as an argument

The C++ version is:

std::ostream& operator<<(std::ostream& out, const complex& c) {   return out << "(" << c.x << "," << c.y << ")";}// Usage:complex c;std::cout << c;std::cerr << c;std::clog << c;std::ofstream fout("foo.txt");fout << c;std::stringstream sout;sout << "The complex is '" << c << "'.";mystream mout;mout << c;


Of course, binary writing is possible in the exact same way.
Plus c++ streams are designed to work well with generic programming methods as well (ala templates). This means they are compatable with the various algorithms that are available to in the standard c++ library (see ostream_iterator and istream_iterator for details).

eg:

std::vector<int> v;// copy typed in numbers into a vectorstd::copy(  std::istream_iterator(std::cin, ' '),  std::istream_iterator(),  std::back_inserter(v)  ); // write vector to screenstd::copy(  v.begin(),  v.end(),  ostream_iterator(std::cout, '\n' )  );


And adding that to what ToohrVyk said makes it possible to do that with anything that derives from istream ad ostream (which bothe derive from stream)
[size=2]aliak.net
Another of advantage of C++'s method of file I/O that's worth mentioning in it's own category is it's type safe.

With C style *printf, your compiler will at best warn you (which if you accidentally skim over to work on later, may not come up again for quite awhile if you're using conditional recompilaiton), and at worst silently cause runtime failures if you mismatch the variable type and format specifier. This also causes mantinence nightmares for changing types as every format string by necessity repeats the variable type, and thus must be updated in sync.

Worse yet, behavior is completely undefined if you pass an object to a va_args using function.

On the other hand, C++ streams don't force you to repeat the type. It uses operator overloading to select the appropriate formatting option based on type. It works sanely with custom classes, and it's downright impossible to mismatch the number of format specifiers and display arguments.

Those advantages that format specifiers do have - namely, discoupling format from the code that wants to display a formatted string - can be accomplished using the boost::format library, which interoperates with C++'s iostreams for all of the advantages and none of the avoidable disadvantages:

1) Unlike *printf, boost::format still uses operator chaining to accomplish it's argument input, meaning it can automatically deduce types and number of arguments safely.

2) While like *printf it's possible to mismatch format specifiers and the total number of arguments with boost::format, unlike *printf, this has specified and defined behavior, rather than undefined "launch nukes at a cow ranch in Alaska for all I care" va_args behavior.

This has been a message from the "all you ever wanted to know about the advantages of iostreams over FILE*s, and then some" department of information.
Quote:Original post by ToohrVyk
Streams are adapted to C++'s object-oriented approach. In particular, polymorphism allows them to be extended globally instead of individually. Using C, and typedef struct { float x; float y; } complex;, write a single function to write a complex in text form to:
- the standard output, error output, or log
- a file
- another string
- any kind of equivalent object, passed as an argument

The C++ version is:

*** Source Snippet Removed ***

Of course, binary writing is possible in the exact same way.


Why would you manipulate a stream using ostream say instead of just using ofstream/cout on any object data you need. A more manula way I guess.

What benefit is there as it seems a more complicated way to use files?
Quote:Original post by jagguy
Why would you manipulate a stream using ostream say instead of just using ofstream/cout on any object data you need. A more manula way I guess.

What benefit is there as it seems a more complicated way to use files?


You've got your view reversed, that's all.

The benefit of using an ostream instead of a concrete implementation of an ostream is that you've separate the concept of a stream from the concept of a file, or a string, or a socket, or a hyperspace transporter. Your object doesn't care about the internals of where it's serializing its data to.

With C, your object would have to know where your data is going, and use fprintf() or sprintf() or send() or whatever. With C++, you just stream to an ostream and let the ostream object woryy about which orifice it's filling.

This is a basic idiom in object-oriented design.

Stephen M. Webb
Professional Free Software Developer

Quote:
so why did c++ reinvent file operations?

For what it's worth, the difference between the C standard library file IO routines and the C++ standard library file IO routines is largely one of interface (in that the C++ version's interface has all of the aforementioned advantages).

Neither really constitute a "reinvention" of the actual file operations, which in the long run all call down to the file IO routines of whatever operating system you're running.
Bregma, nice way to put it... quite colorful [cool]

I think it should be noted that the advantages in using streams instead of FILE pointers, etc, is completely dependent on implementation and circumstance. IE: it is somewhat silly to use a stream to open a single file of known name and format from which you are reading a string of known size (bad example, I know). But generally, streams are a better idea if you are concerned about runtime errors since the printf functions are rather difficult to debug (however you will run into far more problems when using the sprintf functions... those seem to enjoy causing headaches).
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
Quote:
I think it should be noted that the advantages in using streams instead of FILE pointers, etc, is completely dependent on implementation and circumstance.

I disagree; if you are using C++, I don't see any reason to use the C file IO routines.

Quote:
it is somewhat silly to use a stream to open a single file of known name and format from which you are reading a string of known size (bad example, I know)

Yes, terrible example. How is this "silly?"
{std::ifstream  fp("test.txt");std::string    s;  fp >> s;}

When compared to the C equivalent, this is cleaner, safer, and shorter. Where's the disadvantage? Where's the "silliness?"

Don't use C when you're writing C++.
It also has much more overhead. But anyway, it is certainly shorter and safer.

I must say, though, the concept of not using C when writing C++ is more than slightly crazy. Especially because the old standard headers are not technically part of the language. When you are writing C++ you ARE writing C except that you are also using some newer features such as classes, etc. So lets revise that to say "Don't use C libraries when you're writing C++". Sorry, I digress.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

This topic is closed to new replies.

Advertisement