写文件的几种方式及其效率对比
将100万条字符串写入到文件里,有几种方法.
方法一,直接流入std::ofstream
for (int i=0; i<1000000; i++)
{
ofile << s << std::endl;
}
耗时13s。
考虑到std::endl会做fflush,导致触发write系统调用将进程内缓存刷到OS缓冲,从而影响写效率,我们改为使用"\n":
int n = 1000000;
for (int i=0; i<n; i++)
{
outf << s << "\n";
}
仅耗时1s。不过,这里效率的提升是以可靠性为代价的,一旦当前进程core掉,未及时刷到os缓冲区的内容会丢失掉。
方法二,先流入std::ostringstream,凑够一定的条数,再流入std::ofstream
void cacheWrite(int n, const std::string& s, std::ofstream& ofile)
{
int maxNum = 2000;
int curNo = 0;
std::ostringstream ss;
for (int i=0; i<n; i++)
{
ss << s << std::endl;
curNo++;
if(curNo > maxNum)
{
ofile << ss.str();
curNo = 0;
ss.str("");
}
}
if(curNo > 0)
{
ofile << ss.str();
}
}
耗时1s。
方法二相比于方法一没有提升,是因为std::ofstream里已经有一个write buffer了,无需我们在应用程序里额外做一个。
扩展
我们通常还会遇到这样的情况:从一个文件读入内容,再追加到另一个文件结尾。业务上合并文件就是这种情况。
同样的,我们有几种做法:
方法一,读一行,写一行
std::string text;
while (getline(inFile, text, '\n') )
{
ofile << text << "\n";
}
100万条消息的文件复制要花费3~4s。
方法二,利用rdbuf,一次性写入:
ofile << inFile.rdbuf();
100万条消息的文件复制也要花费3~4s。
方法二无论是在windows下还是linux下,都是最高效、最简洁的写法。