我有一个包含数百万行的文件,每行有3个以空格分隔的浮点数.读取文件需要花费大量时间,因此我尝试使用内存映射文件读取它们,但发现问题不在于IO的速度,而在于解析速度.
我当前的解析是获取流(称为文件)并执行以下操作
float x,y,z;
file >> x >> y >> z;
Run Code Online (Sandbox Code Playgroud)
Stack Overflow中的某些人建议使用Boost.Spirit,但我找不到任何简单的教程来解释如何使用它.
我正在尝试找到一种简单有效的方法来解析看起来像这样的行:
"134.32 3545.87 3425"
Run Code Online (Sandbox Code Playgroud)
我真的很感激一些帮助.我想用strtok来分割它,但我不知道如何将字符串转换为浮点数,我不太确定它是最好的方法.
我不介意解决方案是否会提升.我不介意它是不是有史以来最有效的解决方案,但我确信它可以加倍速度.
提前致谢.
我试图选择一种将积分转换为字符串的标准方法,所以我接着通过测量3种方法的执行时间进行了一次小的性能评估
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <chrono>
#include <random>
#include <exception>
#include <type_traits>
#include <boost/lexical_cast.hpp>
using namespace std;
// 1. A way to easily measure elapsed time -------------------
template<typename TimeT = std::chrono::milliseconds>
struct measure
{
template<typename F>
static typename TimeT::rep execution(F const &func)
{
auto start = std::chrono::system_clock::now();
func();
auto duration = std::chrono::duration_cast< TimeT>(
std::chrono::system_clock::now() - start);
return duration.count();
}
};
// -----------------------------------------------------------
// 2. Define the convertion functions …Run Code Online (Sandbox Code Playgroud) 我想解析一个看起来像这样的文件(类似FASTA的文本格式):
>InfoHeader
"Some text sequence that has a line break after every 80 characters"
>InfoHeader
"Some text sequence that has a line break after every 80 characters"
...
Run Code Online (Sandbox Code Playgroud)
例如:
>gi|31563518|ref|NP_852610.1| microtubule-associated proteins 1A/1B light chain 3A isoform b [Homo sapiens]
MKMRFFSSPCGKAAVDPADRCKEVQQIRDQHPSKIPVIIERYKGEKQLPVLDKTKFLVPDHVNMSELVKI
IRRRLQLNPTQAFFLLVNQHSMVSVSTPIADIYEQEKDEDGFLYMVYASQETFGFIRENE
Run Code Online (Sandbox Code Playgroud)
我用boost :: spirit为此编写了一个解析器.解析器正确地存储标题行和下面的文本序列,std::vector< std::pair< string, string >>但是对于较大的文件(对于100MB文件为17秒)需要很长时间.作为比较,我编写了一个没有boost :: spirit(只是STL函数)的程序,只需复制一个100MB文件的每一行std::vector.整个过程不到一秒钟.用于比较的"程序"不符合目的,但我不认为解析器应该花更长的时间......
我知道有很多其他的FASTA解析器,但我很好奇为什么我的代码很慢.
.hpp文件:
#include <boost/filesystem/path.hpp>
namespace fs = boost::filesystem;
class FastaReader {
public:
typedef std::vector< std::pair<std::string, std::string> > fastaVector;
private:
fastaVector fV;
fs::path file;
public:
FastaReader(const …Run Code Online (Sandbox Code Playgroud) 在我的情况下,我有不同的文件让我们假设我有4GB文件的数据.我想逐行读取该文件并处理每一行.我的一个限制是软件必须在32位MS Windows上运行,或者在64位上运行少量RAM(最小4GB).您还可以假设这些行的处理不是瓶颈.
在当前的解决方案中,我读取该文件ifstream并复制到某个字符串.这是片段的样子.
std::ifstream file(filename_xml.c_str());
uintmax_t m_numLines = 0;
std::string str;
while (std::getline(file, str))
{
m_numLines++;
}
Run Code Online (Sandbox Code Playgroud)
好的,这是有效的,但在这里慢慢地是我的3.6 GB数据的时间:
real 1m4.155s
user 0m0.000s
sys 0m0.030s
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种比这更快的方法,例如我发现如何快速解析C++中空格分隔的浮点数?我喜欢用boost :: mapped_file提出解决方案,但我遇到了另一个问题,如果我的文件是大的,在我的情况下文件1GB大到足以放弃整个过程.我不得不关心内存中的当前数据,可能使用该工具的人的RAM安装量不超过4 GB.
所以我发现了来自boost的mapped_file但是在我的情况下如何使用它?是否可以部分读取该文件并接收这些行?
也许你有另一个更好的解决方案.我必须处理每一行.
谢谢,
巴特