C++ and C file I/O

10,536

Solution 1

Opinion

I don't know of any real project that uses C++ streams. They are too slow and difficult to use. There are several newer libraries like FastFormat and the Boost version that claim to be better there was a piece in the last ACCU Overload magazine about them. Personally I have used the c FILE library for the last 15 years or so in C++ and I can see no reason yet to change.

Speed

Here is small test program (I knock together quickly) to show the basic speed problem:

#include <stdio.h>
#include <time.h>

#include<iostream>
#include<fstream>

using namespace std;

int main( int argc, const char* argv[] )
    {
    const int max = 1000000;
    const char* teststr = "example";

    int start = time(0);
    FILE* file = fopen( "example1", "w" );
    for( int i = 0; i < max; i++ )
        {
        fprintf( file, "%s:%d\n", teststr, i );
        }
    fclose( file );
    int end = time(0);

    printf( "C FILE: %ds\n", end-start );

    start = time(0);
    ofstream outdata;
    outdata.open("example2.dat");
    for( int i = 0; i < max; i++ )
        {
        outdata << teststr << ":" << i << endl;
        }
    outdata.close();
    end = time(0);

    printf( "C++ Streams: %ds\n", end-start );

    return 0;
    }

And the results on my PC:

C FILE: 5s
C++ Streams: 260s

Process returned 0 (0x0)   execution time : 265.282 s
Press any key to continue.

As we can see just this simple example is 52x slower. I hope that there are ways to make it faster!

NOTE: changing endl to '\n' in my example improved C++ streams making it only 3x slower than the FILE* streams (thanks jalf) there may be ways to make it faster.

Difficulty to use

I can't argue that printf() is not terse but it is more flexible (IMO) and simpler to understand, once you get past the initial WTF for the macro codes.

double pi = 3.14285714;

cout << "pi = " << setprecision(5)  << pi << '\n';
printf( "%.5f\n", pi );

cout << "pi = " << fixed << showpos << setprecision(3) << pi << '\n'; 
printf( "%+.3f\n", pi );

cout << "pi = " << scientific << noshowpos << pi<< '\n';
printf( "%e\n", pi );

The Question

Yes, may be there is need of a better C++ library, many be FastFormat is that library, only time will tell.

dave

Solution 2

Please have a look at

http://www.ddj.com/cpp/184403651

then You will prefer C++ I/O than C I/O.

in short C is prefered if you know data size prior to read or write and for speed. C++ is prefered if you don't know data size and for efficient code.

Solution 3

In response to David Allan Finch's answer, I fixed an error in his benchmarking code (he flushed the stream in the C++ version after every single line), and reran the test:

The C++ loop now looks like this:

start = time(0);
{
    ofstream outdata("example2.txt");
    for( int i = 0; i < max; i++ )
    {
        outdata << teststr << ":" << i << "\n"; // note, \n instead of endl
    }
}
end = time(0);

I run 10000000 iterations (10 times more than in the original code, because otherwise, the numbers are just too small for time()'s lousy resolution to give us anything meaningful)) And the output is:

G++ 4.1.2:
C FILE: 4s
C++ Streams: 6s

MSVC9.0:
C FILE: 10s
C++ Streams: 23s

(note, the MSVC version was run on my laptop with a significantly slower harddrive)

But this gives us a performance difference of 1.5-2.3x, depending on the implementation. and other external factors.

Solution 4

The performance differences between printf()/fwrite style I/O and C++ IO streams formatting are very much implementation dependent. Some implementations (visual C++ for instance), build their IO streams on top of FILE * objects and this tends to increase the run-time complexity of their implementation. Note, however, that there was no particular constraint to implement the library in this fashion.

In my own opinion, the benefits of C++ I/O are as follows:

  • Type safety as already stated earlier.
  • Flexibility of implementation. Code can be written to do specific formatting or input to or from a generic ostream or istream object. The application can then invoke this code with any kind of derived stream object. If the code that I have written and tested against a file now needs to be applied to a socket, a serial port, or some other kind of internal stream, you can create a stream implementation specific to that kind of I/O. Extending the C style I/O in this fashion is not even close to possible.
  • Flexibility in locale settings: the C approach of using a single global locale is, in my opinion, seriously flawed. I have experienced cases where I invoked library code (a DLL) that changed the global locale settings underneath my code and completely messed up my output. A C++ stream allows you to imbue() any locale to a stream object.

Solution 5

C and C++ are two different languages. C++ file io takes some time getting used to, but once you are using algorithms, exceptions etc they tend to fall into place very naturally.

Share:
10,536
Chaithra
Author by

Chaithra

Updated on August 03, 2022

Comments

  • Chaithra
    Chaithra almost 2 years

    C++ file I/O is tougher than C file I/O. So in C++, creating a new library for file I/O is useful or not? I mean <fstream> Can anyone please tell are there any benefits in C++ file I/O ?

  • Anonymous
    Anonymous about 15 years
    Maybe he was referring to iomanip formatting? Issues with atomicity/multithreading? Illusionary type safety? And moderate performance?
  • David Allan Finch
    David Allan Finch about 15 years
    I have used C++ since the days of CFront may be my opinion might be worth thinking about. I agree with the /Illusionary type safety/ of Unknowns comment. I would say that 90% of my output code just prints strings and numbers.
  • Anonymous
    Anonymous about 15 years
    Illusionary type safety to be precise.
  • Admin
    Admin about 15 years
    I was a cfront user too. It doesn't make my opinions particularly valid.
  • David Allan Finch
    David Allan Finch about 15 years
    I agree that having used C Front is a bit of a bogus point ;) May be my test will prove that it slower. FastFormat claims to over come these problems.
  • josesuero
    josesuero about 15 years
    your comparison is flawed. The C and C++ versions don't do the same thing. The c++ version flushes the buffer after every line (endl). Sometimes, reading the documentation on the code you use is a good idea.
  • josesuero
    josesuero about 15 years
    Calling printf more flexible is nonsense too. It doesn't work with user-defined types. That's hardly flexible. It is far less flexible than iostreams. And i'd argue that the C++ version is a lot easier to understand. I can guess what setprecision does. %+.3 is less obvious.
  • David Allan Finch
    David Allan Finch about 15 years
    Good point - it has been such a long time since I used C++ streams. i change it to << '\n' and the time changed to 15s so that it is still 3x slower.
  • David Allan Finch
    David Allan Finch about 15 years
    Yes %.3 is not obvious to those that are not in to the idiom of printf but how do you create 0 padded 5 width number in C++ streams?
  • David Allan Finch
    David Allan Finch about 15 years
    Also I though C++ streams was simpler ;) how come endl is slower than '\n' anyway!
  • David Allan Finch
    David Allan Finch about 15 years
    because of the way that things can be autocasted through temporaries things can jump type.
  • Admin
    Admin about 15 years
    I think this illustrates the unsuitability of SO for discussion. Perhaps this should be taken to somewhere like comp.lang.c++.moderated?
  • Jon Trauntvein
    Jon Trauntvein about 15 years
    std::endl is slower than simply inserting a line feed because std::endl is defined to flush the stream at the same time.
  • David Allan Finch
    David Allan Finch about 15 years
    When you change the C FILE to fflush after every write the times are the same. So the Buffered writes in C++ Streams are three times slower but the unbuffered are the same. This is probably because the C++ streams buffer is not implemented well.
  • David Allan Finch
    David Allan Finch about 15 years
    The same code on my UltraSparc I get 9s vs 21s and using /tmp I get 5s vs 16s. Oh and I did edit my answer ;)
  • David Allan Finch
    David Allan Finch about 15 years
    cout << setfill('0') << setw(5) << 1; vs printf( "%05d", 1 );
  • EFraim
    EFraim about 15 years
    BTW setfill('0') << setw(5) seems way more self-explaining than %05.
  • Ankit Roy
    Ankit Roy about 15 years
    @David: Things can jump type, but nothing in the standard libraries does this, and common wisdom is to limit user-defined conversions to a minimum to avoid this.
  • Ankit Roy
    Ankit Roy about 15 years
    @David: OTOH I consider it a bug that the seemingly reasonable code 'std::ofstream("somefile") << "abc");' outputs "0" to somefile on most implementations, due to deep C++ weirdnesses (specifically, some operator<<() overloads are members of iostream while others are free functions).
  • Benj
    Benj over 12 years
    @David: I realise that this was a while ago now.. but I just ran the test program above (without endl) and got very comparable results. In debug mode I got similar results to you but in release mode on VC2010 I get identical results for C and C++. Can I ask if you originally ran this in debug or release?
  • Benj
    Benj over 12 years
    I also get identical (but slower) results if I leave endl in and put an fflush() in for the C method...
  • David Allan Finch
    David Allan Finch over 12 years
    VS2005 in release mode. I have not tested it in a later compiler but I would hope that it has been optimised as the reasons for it slowness should be well know by now. That been said I did bet similar results with other compilers on other platforms. That been said I would still rather (personally) use C FILE or FastFormat but other will disagree and they are just as correct as there are no silver bullets.
  • Joe DF
    Joe DF about 11 years
    C is faster for Input AND Output, than C++.. cybertiggyr.com/ios0/index.html
  • Hawk
    Hawk almost 10 years
    i know this question is very old but C and C++ have no difference in file streaming..see this post stackoverflow.com/questions/17468088/… addition, i read from the post that using endl is more expensive so if you use \n, it will be faster in file IO
  • David Allan Finch
    David Allan Finch almost 10 years
    @Hawk - Originally there was still a three times performance at the time of this Q&A. I would have hoped that it would have been fixed by now.
  • Andrew Henle
    Andrew Henle almost 6 years
    freopen() is standard C, not C++, even though it can be used by C++ code. I fail to see how posting C code that reassigns stdin and stdout makes any case that C++ IO "easier than c". At best, it applies equally to both languages.
  • skyscraper
    skyscraper almost 6 years
    @AndrewHenle freopen() in c++ is defined in a completely different header file which is a lot easier to use than that in C.
  • Andrew Henle
    Andrew Henle almost 6 years
    freopen() in c++ is defined in a completely different header file Do you really think #include <cstdio> is somehow easier than #include <stdio.h>? That seems irrelevant. And - in the case of GCC - you're flat-out wrong as cstdio there is merely some C++ syntactic sugar wrapped around stdio.h..
  • skyscraper
    skyscraper almost 6 years
    @AndrewHenle okay agree , i wanna upvote you but can't .