我写字符串使用文本文件:C++:字符串写入到文件
ofstream ofs("ofs.txt", ios_base::binary);
std::string str = "Hi";
for (int i = 0 ; i < 10000000 ; i++) {
ofs << str.c_str();
ofs << "\n" ;
}
然而,这需要很长的时间来执行。任何人都可以帮助我如何提高上述表现。或者以其他更快的方式将字符串写入文件。
谢谢。
我写字符串使用文本文件:C++:字符串写入到文件
ofstream ofs("ofs.txt", ios_base::binary);
std::string str = "Hi";
for (int i = 0 ; i < 10000000 ; i++) {
ofs << str.c_str();
ofs << "\n" ;
}
然而,这需要很长的时间来执行。任何人都可以帮助我如何提高上述表现。或者以其他更快的方式将字符串写入文件。
谢谢。
在几种情况下,我发现C++ I/O流往往比C <stdio.h> FILE*
慢。
我有一个确认也是在下面的测试:
#define _CRT_SECURE_NO_WARNINGS // for stupid fopen_s warning
#include <stdio.h>
#include <exception>
#include <fstream>
#include <iostream>
#include <ostream>
#include <stdexcept>
#include <string>
#include <vector>
#include <windows.h>
using namespace std;
long long Counter()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return li.QuadPart;
}
long long Frequency()
{
LARGE_INTEGER li;
QueryPerformanceFrequency(&li);
return li.QuadPart;
}
void PrintTime(long long start, long long finish, const char * s)
{
cout << s << ": " << (finish - start) * 1000.0/Frequency() << " ms" << endl;
}
// RAII wrapper to FILE*
class File
{
public:
explicit File(FILE * f)
: m_file(f)
{}
~File()
{
fclose(m_file);
}
FILE* Get() const
{
return m_file;
}
bool IsOpen() const
{
return (m_file != nullptr);
}
private:
FILE* m_file;
File(const File&);
File& operator=(const File&);
};
void TestIoStream(const vector<string>& lines)
{
ofstream ofs("ofs.txt", ios_base::binary);
for(auto it = lines.begin(); it != lines.end(); ++it)
{
ofs << it->c_str();
ofs << "\n" ;
}
}
void TestStdioFile(const vector<string>& lines)
{
File file(fopen("cfile.txt", "wt"));
if (! file.IsOpen())
throw runtime_error("Can't open C FILE*.");
for(auto it = lines.begin(); it != lines.end(); ++it)
{
fputs(it->c_str(), file.Get());
fputs("\n", file.Get());
}
}
int main()
{
static const int kExitOk = 0;
static const int kExitError = 1;
try
{
cout << "Building test lines...";
vector<string> lines;
for (int i = 0; i < 10000000; i++)
lines.push_back("Hi");
cout << "done. ";
cout << "(Count = " << lines.size() << ")" << endl;
long long start = 0;
long long finish = 0;
start = Counter();
TestIoStream(lines);
finish = Counter();
PrintTime(start, finish, "C++ I/O stream");
start = Counter();
TestStdioFile(lines);
finish = Counter();
PrintTime(start, finish, "C FILE*");
return kExitOk;
}
catch(const exception& e)
{
cerr << "\n*** ERROR: " << e.what() << endl;
return kExitError;
}
}
与VS2010 SP1(VC10)编译:
cl /EHsc /W4 /nologo /MT /O2 /GL test.cpp
测试结果:
Building test lines...done. (Count = 10000000) C++ I/O stream: 2892.39 ms C FILE*: 2131.09 ms
只要使用ofs << str;
可能会稍微快一点(或者它可能不会,但它肯定更习惯)。但是你正在写20兆字节的数据;无论你如何做,这都需要一些时间。
你不明确你正在做什么。 (我猜测真正的问题不涉及千万次"Hi"
。)根据这一点,可能会使用低级IO,甚至可能使用mmap
。但是这些都没有格式化,如果你首先格式化为ostringstream
,你可能会发现它们并没有明显更快。
通过C FILE *
接口将大量字符串写入文件的最快方法是(很可能)。当然,C++流接口的性能不如FILE *
。理想情况下,如果您建立几KB(一次4KB)的缓冲区,并使用fwrite(buffer, size_of_buffer, 1, outfile);
编写该缓冲区,则应该非常接近系统的性能。是的,您可以分别使用write
或WriteFile
的本机接口分别对Linux/Unix和Windows调整0.5%左右。
当然缺点是你没有简单的方法来为任意新类型添加一个输出方法。
与往常一样,当涉及到性能时,测量不同的选项,并查看哪些出现最佳。如果在不同环境下许多机器上都会使用它,那么使用不同的硬件,不同的内存和系统负载进行测试也是很好的选择,以确定您不仅仅是让机器运行得更快,对具有不同条件的系统给出合理的改进[或者至少没有坏的缺点]。
你为什么要在二进制模式下编写字符串? –
你只需要在文本模式下打开文件 – Subhajit
@BartekBanachewicz,会导致任何性能开销? – user1838343