c++读写大文件
C++ read/write big files
我是c++新手!因此,如果您能考虑并尽可能简单地回答,我将非常感激。我需要解析>40000序列(近500Mb)的fasta文件,并将ID和序列长度写入新文件。我发现它在c++中运行得非常慢,而在这方面,python的工作速度要快得多。但我需要学习如何在c++中做到这一点。我想知道有什么方法可以使c++的这个过程更加紧密?
这是我的代码:
#include <iostream>
#include <fstream>
#include <string>
#include <time.h>
#include <stdio.h>
using namespace std;
int main() {
time_t start, end;
time(&start);
clock_t begin = clock();
ifstream file;
string line;
string id;
string content;
int len = 0;
int i = 0;
ofstream out;
file.open("contigs.fasta", ios::in);
out.open("output.txt", ios::out);
while (getline(file, line)) {
if (line[0] == '>') {
i++;
if (i != 1) {
//cout << id << "n" << len << "n" << content << endl;
//out.write(line.c_str(), line.size());
out << id << " : " << len << endl;
}
id = line;
len = 0;
content = "";
}
else
{
len += line.length();
content += line;
}
}
//cout << id << "n" << len << "n" << content << endl;
//out << id << " : " << len << endl;
cout << "Total number of sequences :" << i << "n";
out.close();
time (&end);
double dif = difftime (end,start);
printf ("Elasped time is %.2lf seconds.", dif );
return 0;
}
提前感谢!
也许您应该将整个文件或其中的一个块读入预分配的字符串中。然后根据需要使用std::stringstream
来处理文件:下面是我在程序中使用的示例。我的文件没有那么大,但它们包含数千行,然后对每一行进行特定字符的解析,复制等。这只需要几毫秒(对于最大的文件,加载和解析大约需要50毫秒)。
//1- read the file
std::string str; // allocate string
{
//compute file size
int iFileSize = 0;
{
std::ifstream ifstr(rkFilename.c_str(), std::ios::binary); // create the file stream - this is scoped for destruction
if(!ifstr.good())
{
return;
}
//get the file size
iFileSize = ifstr.tellg();
ifstr.seekg( 0, std::ios::end ); // open file at the end to get the size
iFileSize = (I32) ifstr.tellg() - iFileSize;
}
//reopen the file for reading this time
std::ifstream ifstr(rkFilename.c_str());
//create a char* with right size
char* pcFileBuffer = new char[iFileSize];
//copy the full file in there
ifstr.read(pcFileBuffer, iFileSize);
//put it all into a string - could be optimised I guess
str = std::string(pcFileBuffer);
//bookeeping
delete[] pcFileBuffer;
pcFileBuffer = NULL;
}
// create a stream using the allocated string
// this stream works as a file reader basically so you can extract lines into string, etc...
std::stringstream filebuf(str);
//the rest is up to you
如果你没有足够的空间来读取一个完整的500Mb文件到你的内存中,请调整这个来读取一个块…
你可以做的另一个优化。正如@Adrian所说,content += line
相当慢…看看你的代码,你可能想寻找'>'
字符,同时保存开始和停止索引,而不是复制数据。然后,您只需分配一次内存,并使用找到的开始和停止索引复制数据(或者只是构建一个开始和停止索引的数据结构:-))。这就是我用来解析文件的。我使用了std::string
的find_first_of
, find_first_not_of
, find_last_of
和substr
方法。虽然这些可能不是最优的,但它们保持了代码的可读性,并且对于我的目的来说足够快。
我希望我的回答能给你提示,帮助你加快程序的速度。
另外,使用分析器来确定什么花费了您最多的时间也是一个好主意。例如,它在Visual studio 2015上是原生的。
您正在使用out << ... << endl
。这将单行直接刷新到磁盘。因为磁盘不是面向字符的,所以它意味着一个读-修改-写操作。
out << 'n'
将写成换行符。磁盘缓存将处理这个
为什么慢?
fasta文件可能相当大。但这在c++中完全不是问题。最好的方法是使用侧写分析器。
但是在这里,字符串分配是一个很好的候选根本原因:每一行读取都被添加到字符串的末尾,导致字符串增长。这意味着由于content
的增长而导致频繁的重新分配,这会导致内存的分配、复制、重新分配,以及远远超出所需的内存!
这种方法可能会导致堆碎片,并且如果执行数十万次,则会大大减慢进程。幸运的是,有几种策略可以更快地做到这一点。
如何轻松加速
您可以使用reserve()
为content
预分配足够的空间。这可能是一个简单的加速器,特别是如果你知道你的核苷酸的平均大小。但即使你不这样做,它也可以减少很多重新分配的努力。
试着看看是否有区别:
content.reserve (100000); // just before entering into the loop.
如何进一步加速
另一种非常有效的方法是使用seekg()
和tellg()
确定fasta文件的大小,然后使用fread()
在一次读取中将文件加载到内存中,并在读取它的地方直接解析/处理它。
使用这种非常原始的方法,您应该获得Gb/s范围内的吞吐量。
最后但并非最不重要的是,不要忘记在发布模式下编译c++代码(打开优化器)以进行性能测量。
- 用C++快速读写文件
- C++中读/写二进制文件
- 为什么使用_access时只读测试对读写文件有效
- 谷歌测试读写同一文件失败
- UWP 是否有同步文件读/写 API
- 为什么SDL_RWFromFile(文件,"w+")不能像它应该的那样读写?它只打开文件进行写入
- 如何使用 Dlang 或 cpp 捕获和修改对文件的读写
- 如何读写结构向量到文件
- 读/写二进制文件返回0xcccccccccccc
- C++中大文件读/写的性能问题
- 读/写文件导致错误。(javaScript & C++)
- 逐行读取文件时,文件读写
- 调试读/写字符串到二进制文件
- 使用boost iostreams将数组读写到压缩文件中
- 用c++读写多个文件
- 提升内存映射文件:读写访问
- C++在g++和msvc之间不同的文件读/写时间
- 将C++文件读写转换为C#文件读写
- c++用二进制文件读/写对象
- 文件读写会产生valgrind错误