1

我正在使用以下方法将字符串写入文本文件:

ofstream ofs("ofs.txt", ios_base::binary);
std::string str = "Hi";
for (int i = 0 ; i < 10000000 ; i++) {
    ofs << str.c_str();
    ofs << "\n" ;
}

但是,这需要很长时间才能执行。任何人都可以帮助我如何提高上述性能。或任何其他将字符串写入文件的更快方法。

谢谢。

4

3 回答 3

1

只是使用ofs << str;可能会稍微快一些(或者可能不会,但它肯定更惯用)。但是您正在写入 20 兆字节的数据;这需要一些时间,不管你怎么做。

你没有准确地说出你想要做什么。(我猜真正的问题不会涉及一千万次"Hi"。)根据这一点,可能可以使用低级 IO,甚至mmap. 但是这些都不做任何格式化,如果你必须格式化为ostringstream第一个,你可能会发现它们并没有明显更快。

于 2013-02-08T11:17:50.233 回答
1

将大量字符串写入文件的最快方法是(很可能)通过 CFILE *接口。C++ 流接口不如FILE *.

理想情况下,如果您建立一个几 KB 的缓冲区(最好是一次 4 KB),并使用 写入该缓冲区fwrite(buffer, size_of_buffer, 1, outfile);,您应该会非常接近系统可以产生的性能。是的,您可以分别使用writeWriteFile用于 Linux/Unix 和 Windows 的本机接口将其调整半个百分点左右。

当然,缺点是您没有简单的方法来简单地为任意新类型添加输出方法。

与往常一样,在性能方面,衡量不同的选项,看看哪个效果最好。如果它是要在不同情况下在许多机器上使用的东西,那么最好用不同的硬件、不同的内存量和系统负载进行测试,以确定你不仅让你的机器运行得更快,而且它实际上在具有不同条件的系统上给出了合理的改进[或至少没有坏的缺点]。

于 2013-02-08T11:51:39.553 回答
1

在某些情况下,我发现 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
于 2013-02-08T12:01:56.380 回答