读取文件c ++的最快方法
Fastest way to read in a file c++
我想读入这样的文件:
13.3027 29.2191 2.39999
13.3606 29.1612 2.39999
13.3586 29.0953 2.46377
13.4192 29.106 2.37817
它有超过 1mio 行。
我当前的 cpp 代码是:
loadCloud(const string &filename, PointCloud<PointXYZ> &cloud)
{
print_info("\nLoad the Cloud .... (this takes some time!!!) \n");
ifstream fs;
fs.open(filename.c_str(), ios::binary);
if (!fs.is_open() || fs.fail())
{
PCL_ERROR(" Could not open file '%s'! Error : %s\n", filename.c_str(), strerror(errno));
fs.close();
return (false);
}
string line;
vector<string> st;
while (!fs.eof())
{
getline(fs, line);
// Ignore empty lines
if (line == "")
{
std::cout << " this line is empty...." << std::endl;
continue;
}
// Tokenize the line
boost::trim(line);
boost::split(st, line, boost::is_any_of("\t\r "), boost::token_compress_on);
cloud.push_back(PointXYZ(float(atof(st[0].c_str())), float(atof(st[1].c_str())), float(atof(st[2].c_str()))));
}
fs.close();
std::cout<<" Size of loaded cloud: " << cloud.size()<<" points" << std::endl;
cloud.width = uint32_t(cloud.size()); cloud.height = 1; cloud.is_dense = true;
return (true);
}
目前读取此文件需要很长时间。我想加快这个速度,有什么想法该怎么做吗?
您可以只读取数字而不是整行加上解析,只要数字总是三个一组。
void readFile(const std::string& fileName)
{
std::ifstream infile(fileName);
float vertex[3];
int coordinateCounter = 0;
while (infile >> vertex[coordinateCounter])
{
coordinateCounter++;
if (coordinateCounter == 3)
{
cloud.push_back(PointXYZ(vertex[0], vertex[1], vertex[2]));
coordinateCounter = 0;
}
}
}
您是否运行 优化了代码?在我的机器上,您的代码在 1800 毫秒内读取了一百万个值。
trim
和 split
可能占用了大部分时间。如果字符串开头有白色 space trim
必须复制整个字符串内容以擦除第一个字符。 split
正在创建新的字符串副本,您可以使用 string_view
来优化它以避免副本。
因为你的分隔符是白色的space你可以用这样的代码避免所有的副本:
bool loadCloud(const string &filename, std::vector<std::array<float, 3>> &cloud)
{
ifstream fs;
fs.open(filename.c_str(), ios::binary);
if (!fs)
{
fs.close();
return false;
}
string line;
vector<string> st;
while (getline(fs, line))
{
// Ignore empty lines
if (line == "")
{
continue;
}
const char* first = &line.front();
const char* last = first + line.length();
std::array<float, 3> arr;
for (float& f : arr)
{
auto result = std::from_chars(first, last, f);
if (result.ec != std::errc{})
{
return false;
}
first = result.ptr;
while (first != last && isspace(*first))
{
first++;
}
}
if (first != last)
{
return false;
}
cloud.push_back(arr);
}
fs.close();
return true;
}
在我的机器上,这段代码运行时间为 650 毫秒。大约 35% 的时间被 getline
使用,45% 的时间用于解析浮点数,剩下的 20% 被 push_back
.
使用
一些注意事项:
- 我在调用
getline
后通过检查流的状态修复了 while(!fs.eof())
问题
- 我已将结果更改为数组,因为您的示例不是 mcve,所以我没有
PointCloud
或 PointXYZ
的定义,这可能是这些类型是您速度缓慢的原因。
- 如果您事先知道行数(或至少是一个近似值),那么保留向量的大小将提高性能
我想读入这样的文件:
13.3027 29.2191 2.39999
13.3606 29.1612 2.39999
13.3586 29.0953 2.46377
13.4192 29.106 2.37817
它有超过 1mio 行。
我当前的 cpp 代码是:
loadCloud(const string &filename, PointCloud<PointXYZ> &cloud)
{
print_info("\nLoad the Cloud .... (this takes some time!!!) \n");
ifstream fs;
fs.open(filename.c_str(), ios::binary);
if (!fs.is_open() || fs.fail())
{
PCL_ERROR(" Could not open file '%s'! Error : %s\n", filename.c_str(), strerror(errno));
fs.close();
return (false);
}
string line;
vector<string> st;
while (!fs.eof())
{
getline(fs, line);
// Ignore empty lines
if (line == "")
{
std::cout << " this line is empty...." << std::endl;
continue;
}
// Tokenize the line
boost::trim(line);
boost::split(st, line, boost::is_any_of("\t\r "), boost::token_compress_on);
cloud.push_back(PointXYZ(float(atof(st[0].c_str())), float(atof(st[1].c_str())), float(atof(st[2].c_str()))));
}
fs.close();
std::cout<<" Size of loaded cloud: " << cloud.size()<<" points" << std::endl;
cloud.width = uint32_t(cloud.size()); cloud.height = 1; cloud.is_dense = true;
return (true);
}
目前读取此文件需要很长时间。我想加快这个速度,有什么想法该怎么做吗?
您可以只读取数字而不是整行加上解析,只要数字总是三个一组。
void readFile(const std::string& fileName)
{
std::ifstream infile(fileName);
float vertex[3];
int coordinateCounter = 0;
while (infile >> vertex[coordinateCounter])
{
coordinateCounter++;
if (coordinateCounter == 3)
{
cloud.push_back(PointXYZ(vertex[0], vertex[1], vertex[2]));
coordinateCounter = 0;
}
}
}
您是否运行 优化了代码?在我的机器上,您的代码在 1800 毫秒内读取了一百万个值。
trim
和 split
可能占用了大部分时间。如果字符串开头有白色 space trim
必须复制整个字符串内容以擦除第一个字符。 split
正在创建新的字符串副本,您可以使用 string_view
来优化它以避免副本。
因为你的分隔符是白色的space你可以用这样的代码避免所有的副本:
bool loadCloud(const string &filename, std::vector<std::array<float, 3>> &cloud)
{
ifstream fs;
fs.open(filename.c_str(), ios::binary);
if (!fs)
{
fs.close();
return false;
}
string line;
vector<string> st;
while (getline(fs, line))
{
// Ignore empty lines
if (line == "")
{
continue;
}
const char* first = &line.front();
const char* last = first + line.length();
std::array<float, 3> arr;
for (float& f : arr)
{
auto result = std::from_chars(first, last, f);
if (result.ec != std::errc{})
{
return false;
}
first = result.ptr;
while (first != last && isspace(*first))
{
first++;
}
}
if (first != last)
{
return false;
}
cloud.push_back(arr);
}
fs.close();
return true;
}
在我的机器上,这段代码运行时间为 650 毫秒。大约 35% 的时间被 getline
使用,45% 的时间用于解析浮点数,剩下的 20% 被 push_back
.
一些注意事项:
- 我在调用
getline
后通过检查流的状态修复了 - 我已将结果更改为数组,因为您的示例不是 mcve,所以我没有
PointCloud
或PointXYZ
的定义,这可能是这些类型是您速度缓慢的原因。 - 如果您事先知道行数(或至少是一个近似值),那么保留向量的大小将提高性能
while(!fs.eof())
问题