需使用VS2017及以上版本,C++语言标准选择C++17,支持OpenMP。
执行效率明显优于ifstream + stof。
// 点云数据结构
struct PointXYZ {
std::array<float, 3> coord;
};
float string_to_float_fast(const std::string& str) {
float value;
auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value);
if (ec != std::errc()) {
// 处理错误(如非数字字符串)
return 0.0f; // 或抛出异常
}
return value;
}
uint8_t string_to_uchar_fast(const std::string& str) {
unsigned int value;
auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value);
if (ec != std::errc() || value > 255) {
return 0; // 错误处理
}
return static_cast<uint8_t>(value);
}
bool read_pointcloud_parallel(const std::string& filename, std::vector<PointData>& cloud) {
struct CSVRow {
std::string col1, col2, col3;
};
// --- 1. 打开文件并内存映射 ---
HANDLE hFile = CreateFileA(
filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//throw std::runtime_error("Failed to open file");
printf("Failed to open file");
return false;
}
DWORD fileSize = GetFileSize(hFile, NULL);
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
CloseHandle(hFile);
printf("Failed to create file mapping");
return false;
//throw std::runtime_error("Failed to create file mapping");
}
const char* mappedData = static_cast<const char*>(
MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, fileSize));
if (mappedData == NULL) {
CloseHandle(hMapping);
CloseHandle(hFile);
throw std::runtime_error("Failed to map view of file");
}
// --- 2. 分块并行解析 ---
std::vector<CSVRow> rows;
rows.reserve(1000000); // 预分配
//#pragma omp parallel
{
// 每个线程处理一块数据
int numThreads = omp_get_num_threads();
int threadId = omp_get_thread_num();
size_t chunkSize = fileSize / numThreads;
size_t start = threadId * chunkSize;
size_t end = (threadId == numThreads - 1) ? fileSize : (threadId + 1) * chunkSize;
// 调整起始位置到行首
if (threadId != 0) {
while (start < fileSize && mappedData[start] != '\n') start++;
if (start < fileSize) start++;
}
// 解析当前块
std::vector<CSVRow> localRows;
size_t pos = start;
while (pos < end) {
size_t lineEnd = pos;
while (lineEnd < fileSize && mappedData[lineEnd] != '\n') lineEnd++;
std::string line(mappedData + pos, lineEnd - pos);
pos = lineEnd + 1;
// 分号分割3列
size_t col1End = line.find(';');
size_t col2End = line.find(';', col1End + 1);
if (col3End != std::string::npos) {
//#pragma omp critical
rows.emplace_back(CSVRow{
line.substr(0, col1End),
line.substr(col1End + 1, col2End - col1End - 1),
line.substr(col2End + 1)
});
}
}
}
// --- 3. 清理资源 ---
UnmapViewOfFile(mappedData);
CloseHandle(hMapping);
CloseHandle(hFile);
cloud.resize(rows.size());
#pragma omp parallel for
for (int i = 0;i < rows.size();i++)
{
cloud[i].coord[0] = string_to_float_fast(rows[i].col1);
cloud[i].coord[1] = string_to_float_fast(rows[i].col2);
cloud[i].coord[2] = string_to_float_fast(rows[i].col3);
}
return true;
}