高效读取 3MB 文本文件,包括解析
Efficient read of a 3MB text file incl. parsing
我有几个~3MB的文本文件,我需要在C++中解析。
文本文件如下所示(1024x786
(:
12,23 45,78 90,12 34,56 78,90 ...
12,23 45,78 90,12 34,56 78,90 ...
12,23 45,78 90,12 34,56 78,90 ...
12,23 45,78 90,12 34,56 78,90 ...
12,23 45,78 90,12 34,56 78,90 ...
表示用Tab
分隔的"数字块",数字本身包含,
(而不是.
(小数点标记。
首先,我需要读取文件。目前我正在使用这个:
#include <boost/tokenizer.hpp>
string line;
ifstream myfile(file);
if (myfile.is_open())
{
char_separator<char> sep("t");
tokenizer<char_separator<char>> tokens(line, sep);
}
myfile.close();
这在为我提供"数字块"方面效果很好,但我仍然需要将此char
转换为浮点数,但将,
作为小数标记处理。由于文件大小,我认为tokenize
这个也不是一个好主意。此外,我需要将所有这些值添加到数据结构中,之后我可以按位置访问该结构(例如[x][y]
(。任何想法如何实现这一目标?
您可以使用Boost.Spirit来解析文件的内容,作为最终结果,您可以从解析器中获得您喜欢的结构数据,例如,std::vector<std::vector<float>>
。IMO,您的常见文件大小不大。我认为最好将整个文件读取到内存中并执行解析器。读取文件的有效解决方案如下所示read_file
.
qi::float_
分析长度和大小受float
类型限制的实数,并使用.
(点(作为分隔符。您可以通过qi::real_policies<T>::parse_dot
自定义分隔符。下面我使用的是来自spirit/example/qi/german_floating_point.cpp
的代码片段。
看看这个演示:
#include <boost/spirit/include/qi.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
std::string read_file(std::string path)
{
std::string str;
std::ifstream file( path, std::ios::ate);
if (!file) return str;
auto size(file.tellg());
str.resize(size);
file.seekg(0, std::ios::beg);
file.rdbuf()->sgetn(&str[0], size);
return str;
}
using namespace boost::spirit;
//From Boost.Spirit example `qi/german_floating_point.cpp`
//Begin
template <typename T>
struct german_real_policies : qi::real_policies<T>
{
template <typename Iterator>
static bool parse_dot(Iterator& first, Iterator const& last)
{
if (first == last || *first != ',')
return false;
++first;
return true;
}
};
qi::real_parser<float, german_real_policies<float> > const german_float;
//End
int main()
{
std::string in(read_file("input"));
std::vector<std::vector<float>> out;
auto ret = qi::phrase_parse(in.begin(), in.end(),
+(+(german_float - qi::eol) >> qi::eol),
boost::spirit::ascii::blank_type{},
out);
if(ret && in.begin() == in.end())
std::cout << "Success" << std::endl;
}
我会直接做什么(根本不需要boost::tokenizer
(:
std::setlocale(LC_NUMERIC, "de_DE"); // Use ',' as decimal point
std::vector<std::vector<double>> dblmat;
std::string line;
while(std::getline(myfile,line)) {
dblmat.push_back(std::vector<double>());
std::istringstream iss(line);
double val;
while(iss >> val) {
dblmat.back().push_back(val);
}
}
相关文章:
- 私有,包括头文件
- 包括头文件或 cpp 文件
- cpp 在主源文件中包括.cpp文件导致错误"duplicate symbol"
- 对"列表"的引用不明确,包括头文件
- 在 UWP 视觉工作室项目中包括外部文件夹
- 包括.cpp文件和.h文件的差异(在CPP中具有相同的内容)
- C++包括头文件
- 使用 Matlab Coder 将 Matlab m 文件转换为 C/C++ 代码,包括 mex 文件 (mxArray
- 包括新文件夹中的头文件 "cannot open include file - no such file or directory"
- 我如何grep通过所有文件#包括在文件中当前打开的vim
- g++未定义的引用,尽管包括所有文件
- 包括.cpp文件
- 包括头文件(包括它们自己)
- 在头文件中包括头文件
- 如何从文件夹中读取所有txt文件?(包括子文件夹)
- 名称空间,包括cpp文件中具有相同名称的函数
- 包括.cpp文件
- 在我的项目中包括ini文件
- 如何调用一个c++函数,而不包括头文件和副本
- 用g++编译-包括头文件