更快地创建制表符分隔的文本文件?

时间:2010-01-18 11:31:06

标签: c++

我的许多程序输出大量数据供我在Excel上查看。查看所有这些文件的最佳方法是使用制表符分隔文本格式。目前我使用这段代码来完成它:

ofstream output (fileName.c_str());
for (int j = 0; j < dim; j++)
{
    for (int i = 0; i < dim; i++)
        output << arrayPointer[j * dim + i] << " ";
    output << endl;
}

这似乎是一个非常慢的操作,是一种更有效的方式输出像这样的文本文件到硬盘驱动器?

更新:

考虑到这两个建议,新代码是这样的:

ofstream output (fileName.c_str());
for (int j = 0; j < dim; j++)
{
    for (int i = 0; i < dim; i++)
        output << arrayPointer[j * dim + i] << "\t";
    output << "\n";
}
output.close();

以500KB / s的速度写入HD

但这会以50MB / s的速度写入HD

{
    output.open(fileName.c_str(), std::ios::binary | std::ios::out);
    output.write(reinterpret_cast<char*>(arrayPointer), std::streamsize(dim * dim * sizeof(double)));
    output.close();
}

6 个答案:

答案 0 :(得分:6)

使用C IO,它比C ++ IO快得多。我听说编程竞赛中的人们因为使用C ++ IO而不是C IO而超时。

#include <cstdio>

FILE* fout = fopen(fileName.c_str(), "w");

for (int j = 0; j < dim; j++) 
{ 
    for (int i = 0; i < dim; i++) 
        fprintf(fout, "%d\t", arrayPointer[j * dim + i]); 
    fprintf(fout, "\n");
} 
fclose(fout);

只需将%d更改为正确的类型。

答案 1 :(得分:3)

不要使用endl。它将刷新流缓冲区,这可能是非常低效的。代替:

output << '\n';

答案 2 :(得分:2)

我决定测试JPvdMerwe's claim C stdio比C ++ IO流更快。 (剧透:是的,但不一定很多。)为此,我使用了以下测试程序:

通用包装器代码,在以下程序中省略:

#include <iostream>
#include <cstdio>
int main (void) {
  // program code goes here
}

程序1:正常同步的C ++ IO流

for (int j = 0; j < ROWS; j++) {
  for (int i = 0; i < COLS; i++) {
    std::cout << (i-j) << "\t";
  }
  std::cout << "\n";
}

程序2:未同步的C ++ IO流

与程序1相同,但前缀为std::cout.sync_with_stdio(false);除外。

计划3:C stdio printf()

for (int j = 0; j < ROWS; j++) {
  for (int i = 0; i < COLS; i++) {
    printf("%d\t", i-j);
  }
  printf("\n");
}

使用以下命令在Ubuntu Linux上使用GCC 4.8.4编译所有程序:

g++ -Wall -ansi -pedantic -DROWS=10000 -DCOLS=1000 prog.cpp -o prog

并使用命令定时:

time ./prog > /dev/null

以下是我的笔记本电脑上的测试结果(以挂钟时间测量):

  • 程序1(同步C ++ IO): 3.350s (= 100%)
  • 程序2(未同步的C ++ IO): 3.072s (= 92%)
  • 计划3(C stdio): 2.592s (= 77%)

我还使用g++ -O2运行相同的测试来测试优化的效果,并得到以下结果:

  • 程序1(同步C ++ IO)与-O2 3.118s (= 100%)
  • 程序2(不同步的C ++ IO)-O2 2.943s (= 94%)
  • 计划3(C stdio)-O2 2.734s (= 88%)

(最后一行不是侥幸;程序3对-O2的持续运行速度比没有它的速度慢!)

因此,我的结论是,基于此测试,C stdio确实比(同步)C ++ IO快10%到25%。使用未同步的C ++ IO可以比同步IO节省大约5%到10%,但仍然比stdio慢。

聚苯乙烯。我也尝试了其他一些变体:

  • 正如预期的那样,使用std::endl代替"\n"稍慢,但上面给出的参数值的差异小于5%。但是,打印更多但更短的输出行(例如-DROWS=1000000 -DCOLS=10)会使std::endl"\n"慢30%以上。

  • 将输出管道输入普通文件而不是/dev/null会使所有程序减慢约0.2秒,但对结果没有任何定性差异。

  • 将行数增加10倍也不会产生任何意外;正如预期的那样,这些程序的运行时间大约要长10倍。

  • std::cout.sync_with_stdio(false);预先添加到计划3中没有明显的效果。

  • 使用(double)(i-j)(和"%g\t" printf())可以减慢所有三个程序的速度!值得注意的是,程序3仍然是最快的,只需9.3秒,其中程序1和2各自超过14秒,加速度接近40%! (是的,我检查过,输出是相同的。)使用-O2也没有显着差异。

答案 3 :(得分:1)

是否必须用C语言编写?如果没有,有许多工具已经用C编写,例如(g)awk(可以在unix / windows中使用),它可以很好地完成文件解析,也适用于大文件。

awk '{$1=$1}1' OFS="\t" file

答案 4 :(得分:1)

这样做可能会更快:

ofstream output (fileName.c_str());
for (int j = 0; j < dim; j++)
{
    for (int i = 0; i < dim; i++)
        output << arrayPointer[j * dim + i] << '\t';
    output << '\n';
}

答案 5 :(得分:0)

ofstream output (fileName.c_str());
for (int j = 0; j < dim; j++)
{
    for (int i = 0; i < dim; i++)
        output << arrayPointer[j * dim + i] << '\t';
    output << endl;
}

使用'\ t'而不是“”