C++ C++;尽可能快地将字符串逐行保存到文件中

C++ C++;尽可能快地将字符串逐行保存到文件中,c++,c++11,C++,C++11,我试图写入一个文件或将字符串s.substr(space\u pos)尽快保存到一个向量中。我试图用流的将其写入文件,或者用cout将其输出,但这需要很长时间。文本文件的大小为130mb 代码如下: fstream f(legitfiles.c_str(), fstream::in ); string s; while(getline(f, s)){ size_t space_pos = s.rfind(" ") + 1; cout << s.substr(spac

我试图写入一个文件或将字符串
s.substr(space\u pos)
尽快保存到一个向量中。我试图用流的
将其写入文件,或者用
cout
将其输出,但这需要很长时间。文本文件的大小为130mb

代码如下:

fstream f(legitfiles.c_str(), fstream::in );
string s;
while(getline(f, s)){
    size_t space_pos = s.rfind(" ") + 1;

    cout << s.substr(space_pos) << endl;
    ofstream results("results.c_str()");
    results << s.substr(space_pos) << endl;
    results.close();

}
cout << s << endl;
f.close();
fstream f(legitfiles.c_str(),fstream::in);
字符串s;
while(getline(f,s)){
大小\u t空间\u位置=s.rfind(“”+1;

CUT< P> Uncouple:C流中的C++流:

std::ios_base::sync_with_stdio(false);
拆下cin和cout之间的联轴器

std::cin.tie(NULL);
现在,不要使用
std::endl
在每行之后不必要地刷新fstream缓冲区,刷新是昂贵的。您应该使用换行符
\n
,将缓冲区刷新留给流

也不要构建不需要的额外字符串。使用字符串视图(防止复制)

如果你没有现代的编译器,就用C字符串

s.data() + space_pos

//编辑:请注意,此答案解决的问题与问题中所述的问题不同。它将复制每一行,从行的开头一直到并包括第一个空格,跳过所有内容

getline()
读取一行的第一个单词并将其丢弃之前,可能会更快,而不是使用
string::find()
std::substr()
。此外,还应避免在每次迭代时打开和关闭输出文件

#include <string>
#include <fstream>

int main()
{
    std::ifstream is{ "input" };
    std::ofstream os{ "output" };
    std::string str;
    str.reserve(1024); // change 1024 to your estimated line length.

    while (is.peek() == ' ' || is >> str, std::getline(is, str)) {
        str += '\n';           // save an additional call to operator<<(char)
        os << str.data() + 1;  // +1 ... skip the space
        // os.write(str.data() + 1, str.length() - 1); // might be even faster
    }
}
#包括
#包括
int main()
{
ifstream是{“输入”};
std::of流操作系统{“输出”};
std::字符串str;
str.reserve(1024);//将1024更改为估计的行长度。
而(is.peek()=''| | is>>str,std::getline(is,str)){

str+='\n';//保存对运算符的附加调用您正在复制子字符串。我建议创建一个临时:

ofstream results("results.c_str()");
while(getline(f, s)){
    size_t space_pos = s.rfind(" ") + 1;
    const std::string sub_string(s.substr(space_pos));
    cout << sub_string << "\n";
    results << sub_string << "\n";
}
results.close();
第二个片段背后的想法是,您绕过了格式化过程,直接将字符串的内容写入输出流。您需要测量两个片段,看看哪个更快(启动时钟,运行至少1E6次迭代的示例,停止时钟。取平均值)

如果要加快文件写入速度,请删除对
std::cout
的写入

编辑1:多线程
通过使用多个线程,“读取线程”、“处理线程”和“写入线程”,您可以从中获得更高的效率。
“读取线程”读取行并附加到缓冲区。首先启动此线程。 延迟后,“处理线程”对所有字符串执行substr方法。
处理了大约N个字符串后,“写入线程”启动并将substr字符串写入文件


此技术使用双缓冲。一个线程读取数据并将其放入缓冲区。当缓冲区已满时,处理线程应开始处理并将结果放入第二个缓冲区。当第二个缓冲区已满时,写入线程开始并将缓冲区写入结果文件。应至少有2个“读取”缓冲区和2“写入”缓冲区。应调整缓冲区的数量和大小,以从程序中获得最佳性能。

如果有可用的缓冲区,请运行程序,找出哪些操作正在破坏程序的性能。结果可能是
endl考虑使用“\n”来避免刷新,如果你想“尽可能快”的话,可以阅读一些副本。除了写换行符之外,您可能不应该使用
std::endl
来执行
std::flush
——您可能只想写
'\n'
而不是
std::endl
大多数时候。您是否尝试过通过
open
语句直接写入文件描述符编号和
关闭
?如果您的代码运行正常,并且您想知道如何使其更好,堆栈溢出不适合您。在没有任何变化的情况下问这个问题…写入速度保持不变,我已经尝试过了。@JospehBody使用这些添加内容重试。如果您正在使用文件,则删除刷新会加快速度。但是如果您如果正在使用cin/cout,则在完成后,需要考虑的其他事项很少,然后删除额外的刷新将非常有帮助。
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
使用
fstream
s不增加I/O速度…与原来的不一样。带前导空格的行的处理方式不同。
操作符>
在读取单词之前忽略前导空格。不要认为这与您认为的一样。它也不会解决问题。如果该行从这两个空格?@MartinYork是的,它做了我认为它做的;)问题只是我错过了
s.rfind(“”+1
中的
r
(
ofstream results("results.c_str()");
while(getline(f, s)){
    size_t space_pos = s.rfind(" ") + 1;
    const std::string sub_string(s.substr(space_pos));
    cout << sub_string << "\n";
    results << sub_string << "\n";
}
results.close();
while(getline(f, s))
{
    static const char newline[] = "\n";
    size_t space_pos = s.rfind(" ") + 1;
    const std::string sub_string(s.substr(space_pos));
    const size_t length(sub_string.length());
    cout.write(sub_string.c_str(), length);
    cout.write(newline, 1);
    results.write(sub_string.c_str(), length);
    results.write(newline, 1);
}