提问人:Chaithra 提问时间:3/3/2009 最后编辑:YamanekoChaithra 更新时间:11/14/2023 访问量:11579
C++ 和 C 文件 I/O
C++ and C file I/O
问:
C++ 文件 I/O 比 C 文件 I/O 更难。
那么在C++中,为文件 I/O 创建一个新库是否有用?我的意思是谁能告诉C++文件 I/O 有什么好处吗?<fstream>
答:
很多。缺点也是。有关详细信息,请参阅 C++ 语言常见问题解答。简而言之:类型安全和用户定义的类型。
评论
std::ifstream 和 std::ofstream 已在 STL 库中。您不必创建自己的。
主要优点是所有输出和输入都是类型安全的。
C 和 C++ 是两种不同的语言。C++ 文件 io 需要一些时间来适应,但是一旦你使用算法、异常等,它们往往会非常自然地到位。
意见
我不知道有任何使用 C++ 流的真实项目。它们太慢且难以使用。有几个较新的库,如 FastFormat 和 Boost 版本,声称更好,上一期 ACCU Overload 杂志中有一篇关于它们的文章。就我个人而言,在过去的 15 年左右的 C++ 中使用了 c FILE 库,我认为没有理由改变。
速度
这里有一个小测试程序(我快速拼凑起来)来展示基本的速度问题:
#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;
}
以及我电脑上的结果:
C FILE: 5s
C++ Streams: 260s
Process returned 0 (0x0) execution time : 265.282 s
Press any key to continue.
正如我们所看到的,这个简单的例子慢了 52 倍。我希望有办法让它更快!
注意:在我的示例中将 endl 更改为“\n”改进了 C++ 流,使其仅比 FILE* 流慢 3 倍(感谢 jalf),可能有办法使其更快。
使用难度
我不能说 printf() 并不简洁,但它更灵活 (IMO) 并且更易于理解,一旦你通过了宏代码的初始 WTF。
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 );
问题
是的,可能需要更好的C++库,可能是FastFormat就是那个库,只有时间会证明一切。
戴夫
评论
对我来说,消除缓冲区溢出似乎是 C++ 的一大胜利。
评论
请看一下
http://www.ddj.com/cpp/184403651
那么您将更喜欢 C++ I/O 而不是 C I/O。
简而言之,如果您在读取或写入之前知道数据大小并且速度,则首选 C。 如果您不知道数据大小和高效代码,则首选 C++。
printf()/fwrite 样式 I/O 和 C++ IO 流格式之间的性能差异在很大程度上取决于实现。一些实现(例如可视化 C++)在 FILE * 对象之上构建其 IO 流,这往往会增加其实现的运行时复杂性。但是请注意,以这种方式实现库没有特别的限制。
在我个人看来,C++ I/O 的好处如下:
- 如前所述,类型安全。
- 实施的灵活性。可以编写代码来执行特定的格式设置或输入到泛型 ostream 或 istream 对象或从泛型 ostream 或 istream 对象输入。然后,应用程序可以使用任何类型的派生流对象调用此代码。如果我针对文件编写和测试的代码现在需要应用于套接字、串行端口或其他类型的内部流,则可以创建特定于该类型 I/O 的流实现。
- 语言环境设置的灵活性:在我看来,使用单一全局语言环境的 C 方法存在严重缺陷。我遇到过这样的情况:我调用了库代码(DLL),这些代码更改了代码下的全局区域设置,并完全搞砸了我的输出。C++ 流允许您将任何语言环境灌输给流对象。
为了回应David Allan Finch的回答,我修复了他的基准测试代码中的一个错误(他在每一行之后刷新了C++版本中的流),并重新运行了测试:
C++ 循环现在如下所示:
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);
我运行了 10000000 次迭代(比原始代码多 10 倍,因为否则,数字太小了,以至于 time() 糟糕的分辨率无法给我们任何有意义的东西)) 输出为:
G++ 4.1.2:
C FILE: 4s
C++ Streams: 6s
MSVC9.0:
C FILE: 10s
C++ Streams: 23s
(注意,MSVC 版本在我的笔记本电脑上运行,硬盘速度明显较慢)
但这给了我们 1.5-2.3 倍的性能差异,具体取决于实现。和其他外部因素。
评论
每当我需要在 C++ 文件中获取输入/输出时,我只使用两行。
freopen("input.txt","r",stdin); // for input from file
freopen("output.txt","w",stdout);// for output from file
现在,您可以像往常一样从控制台扫描变量,并且您打印为输出的任何内容都将显示output.txt文件中。
所以我不认为 c++ 中的文件 I/O 很难,它比 c 容易得多。
评论
freopen()
是标准的 C,而不是 C++,尽管它可以被 C++ 代码使用。我看不出如何发布重新分配的 C 代码,并使 C++ IO “比 c 更容易”的任何情况。充其量,它同样适用于两种语言。stdin
stdout
cstdio
只是一些 C++ 语法糖包裹在 stdio.h.
周围。#include <cstdio>
#include <stdio.h>
更现代的更新....在GCC 9.2的快速C++基准测试中运行了类似的代码,现在C++ iostream显示为与等效C IO相比略快(1.1x)。注意:使用“\n”而不是 std::endl 以避免刷新问题。来自快速 c++ 基准测试的图表和实际代码
#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);
我没有看到提到的一件事是 cpp 流(至少是 cin、cout 等)使用 .std::ios_base::sync_with_stdio(false)
上一个:IO 大小与块大小?
下一个:C++ 和 C 文件 I/O
评论