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 ?
-
1tougher? I don't think so.. o_O – Mar 03 '09 at 10:28
-
2Nobody seems to know what you mean by “tougher”. Care to elaborate? At the moment, your question just begs to start a flame war. – Konrad Rudolph Mar 03 '09 at 11:50
-
C is faster... http://cybertiggyr.com/ios0/index.html – Joe DF Mar 07 '13 at 17:36
10 Answers
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, may be FastFormat is that library, only time will tell.
dave

- 36,170
- 5
- 26
- 60

- 1,414
- 8
- 20
-
Maybe he was referring to iomanip formatting? Issues with atomicity/multithreading? Illusionary type safety? And moderate performance? – Anonymous Mar 03 '09 at 10:45
-
If you have an opinion of why they are not difficult to use how about posting an answer! – David Allan Finch Mar 03 '09 at 10:46
-
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. – David Allan Finch Mar 03 '09 at 10:49
-
-
@David: I've seen numerous references to slowness of iostreams around the web, though I've never bothered with my own tests. OTOH, I find that writing an operator<<() for your own classes is a nice way to work, especially when debugging. OT3H, managing state with iostreams is a pain. – j_random_hacker Mar 03 '09 at 11:05
-
You can still use << with FILE* if you want to write it that way :) – David Allan Finch Mar 03 '09 at 11:25
-
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. – David Allan Finch Mar 03 '09 at 11:26
-
17your 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. – jalf Mar 03 '09 at 12:21
-
10Calling 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. – jalf Mar 03 '09 at 12:23
-
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 Mar 03 '09 at 12:37
-
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 Mar 03 '09 at 12:39
-
Also I though C++ streams was simpler ;) how come endl is slower than '\n' anyway! – David Allan Finch Mar 03 '09 at 12:41
-
I think this illustrates the unsuitability of SO for discussion. Perhaps this should be taken to somewhere like comp.lang.c++.moderated? – Mar 03 '09 at 12:49
-
8std::endl is slower than simply inserting a line feed because std::endl is defined to flush the stream at the same time. – Jon Trauntvein Mar 03 '09 at 12:50
-
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 Mar 03 '09 at 12:57
-
@David: std::cout << std::setfill('0') << setw(5) << 1; outputs 00001. Was that what you wanted? As far as I know, everything printf can do, iostreams can do as well. And tbh, I think the syntax for both is awful. :p – jalf Mar 03 '09 at 13:21
-
cout << setfill('0') << setw(5) << 1; vs printf( "%05d", 1 ); – David Allan Finch Mar 03 '09 at 13:27
-
-
7@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 Oct 18 '11 at 15:35
-
I also get identical (but slower) results if I leave endl in and put an fflush() in for the C method... – Benj Oct 18 '11 at 15:39
-
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. – David Allan Finch Oct 19 '11 at 11:51
-
2C is faster for Input AND Output, than C++.. http://cybertiggyr.com/ios0/index.html – Joe DF Mar 07 '13 at 17:34
-
i know this question is very old but C and C++ have no difference in file streaming..see this post http://stackoverflow.com/questions/17468088/performance-difference-between-c-and-c-style-file-io..in addition, i read from the post that using `endl` is more expensive so if you use `\n`, it will be faster in file IO – Hawk Jun 12 '14 at 09:37
-
@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. – David Allan Finch Jun 17 '14 at 09:15
Banishing buffer overruns seems like a big win for C++ to me.
-
And what about the extra cost of the dynamic storage. Have you attually compaired the costs of using it. See: /FastFormat in the last ACCU's Overload/. – David Allan Finch Mar 03 '09 at 10:51
-
I presume you're talking about gets(). Are there any other standard C I/O functions that could overrun a buffer? – j_random_hacker Mar 03 '09 at 11:02
-
-
@Mikeage: Good point, %s in ...scanf() is a buffer overrun waiting to happen. – j_random_hacker Mar 04 '09 at 09:25
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.

- 243,077
- 51
- 345
- 550
-
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 Mar 03 '09 at 13:25
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.

- 4,145
- 23
- 12
Whenever I need to take inputs/give outputs in a file in C++, I just use two lines.
freopen("input.txt","r",stdin); // for input from file
freopen("output.txt","w",stdout);// for output from file
Now you can scan variables as you would normally do from console, and whatever you print as output will be displayed in output.txt file.
So I don't think file I/O in c++ is tough, its rather easier than c.

- 29
- 4
-
[`freopen()` is standard C](https://port70.net/~nsz/c/c11/n1570.html#7.21.5.4), 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. – Andrew Henle Aug 07 '18 at 16:16
-
@AndrewHenle freopen() in c++ is defined in a completely different header file which is a lot easier to use than that in C. – skyscraper Aug 08 '18 at 15:47
-
2*freopen() in c++ is defined in a completely different header file* Do you really think `#include
` is somehow *easier* than `#include – Andrew Henle Aug 08 '18 at 15:55`? 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`.](https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/c_global/cstdio). -
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.

- 4,453
- 6
- 39
- 69
std::ifstream and std::ofstream are already in stl library. You don't have to create your own.
The main benefit is all outputs and inputs are type safety.

- 57,943
- 15
- 89
- 102
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.

- 108,024
- 16
- 131
- 187
Lots. Drawbacks too. See C++ language FAQ for details. In short: type-safety and user-defined types.

- 12,811
- 4
- 46
- 62
-
-
I don't quite understand the "Illusionary" term. It is quite real. Of course shooting yourself in a foot is always an option. – EFraim Mar 03 '09 at 11:36
-
because of the way that things can be autocasted through temporaries things can jump type. – David Allan Finch Mar 03 '09 at 12:48
-
@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. – j_random_hacker Mar 04 '09 at 09:20
-
@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). – j_random_hacker Mar 04 '09 at 09:24
A more modern update.... ran similar code in Quick C++ Benchmarks with GCC 9.2 and now C++ iostream is showing as just slightly faster (1.1x) vs equivalent C IO. Note: using "\n" instead of std::endl for avoid flush issue. Chart from Quick c++ Benchmarks And the actual code
#include<iostream>
#include<fstream>
static void cIO(benchmark::State& state) {
// Code inside this loop is measured repeatedly
FILE *file{fopen("/tmp/example1.dat","w")};
const char* teststr = "example";
auto i{0};
for (auto _ : state) {
fprintf( file, "%s:%d\n", teststr, i++ );
}
fclose(file);
}
// Register the function as a benchmark
BENCHMARK(cIO);
static void cppIO(benchmark::State& state) {
// Code before the loop is not measured
std::ofstream outdata;
outdata.open("/tmp/example2.dat");
const char* teststr = "example";
auto i{0};
for (auto _ : state) {
outdata << teststr << ":" << i++ << "\n";
}
outdata.close();
}
BENCHMARK(cppIO);