当前位置: 首页 > article >正文

C++点云大文件读取

C++点云大文件读取

  • 1. 常规读取
    • 1.1 逐行读取
    • 1.2 逐字节读取
  • 2. 并行读取 (Multithreading)
  • 3. 使用缓冲读取 (Buffered I/O)
  • 4. 内存映射文件 (Memory Mapping)

在C++中读取大文件时,如果需要提高读取速度,可以考虑以下几种方法:

1. 常规读取

常规读取是指直接使用 std::ifstream 或 std::getline 逐个字符或逐行读取文件。适用于小文件或需要逐行处理内容的场景。

1.1 逐行读取

#include <iostream>
#include <fstream>
#include <string>

void read_large_file(const std::string& filename) {
    std::ifstream file(filename);
    if (!file) {
        std::cerr << "Failed to open file" << std::endl;
        return;
    }

    std::string line;
    while (std::getline(file, line)) {
        // 处理读取的行
    }

    file.close();
}

1.2 逐字节读取

#include <iostream>
#include <fstream>

void read_large_file(const std::string& filename) {
    std::ifstream file(filename, std::ios::binary);
    if (!file) {
        std::cerr << "Failed to open file" << std::endl;
        return;
    }

    char byte;
    while (file.get(byte)) {
        // 处理读取的字节
    }

    file.close();
}

2. 并行读取 (Multithreading)

对于大文件,如果处理的内容可以并行化(例如按行、按块处理),可以使用多线程来加速读取过程。在多核处理器上,这种方法能够显著提升文件读取的性能。可以使用标准库的 std::thread 或者并行框架如 OpenMP、TBB 等来实现。

复制代码
#include <iostream>
#include <fstream>
#include <vector>
#include <thread>

void process_chunk(const std::vector<char>& buffer, size_t start_idx, size_t end_idx) {
    // 处理 buffer[start_idx, end_idx] 范围内的数据
}

void read_large_file(const std::string& filename) {
    std::ifstream file(filename, std::ios::binary);
    if (!file) {
        std::cerr << "Failed to open file" << std::endl;
        return;
    }

    file.seekg(0, std::ios::end);
    size_t file_size = file.tellg();
    file.seekg(0, std::ios::beg);

    size_t chunk_size = file_size / 4;  // 假设使用 4 个线程
    std::vector<std::thread> threads;

    for (size_t i = 0; i < 4; ++i) {
        size_t start_idx = i * chunk_size;
        size_t end_idx = (i + 1) * chunk_size;
        if (i == 3) end_idx = file_size;

        std::vector<char> buffer(chunk_size);
        file.seekg(start_idx, std::ios::beg);
        file.read(buffer.data(), chunk_size);

        threads.push_back(std::thread(process_chunk, std::ref(buffer), start_idx, end_idx));
    }

    for (auto& t : threads) {
        t.join();
    }

    file.close();
}

3. 使用缓冲读取 (Buffered I/O)

使用缓冲区可以减少频繁的磁盘 I/O 操作,从而加速文件读取过程。C++ 标准库中的 std::ifstream 默认使用缓冲读取。你可以通过调整缓冲区的大小来优化性能。比如,可以使用 std::ifstream 配合 std::vector 来增加读取块的大小。

  • 缓冲区大小的经验值
    对于较小的文件(几 MB),可以选择几 KB 到几十 KB 的缓冲区。
    对于较大的文件(几十 MB 到几 GB),可以选择较大的缓冲区(几百 KB 到 1MB)。
  • 内存的限制
    缓冲区大小也需要考虑系统的内存使用情况。对于非常大的文件(如 10 GB 或更大),如果缓冲区太大,可能会导致内存不足,从而影响系统的性能。根据系统内存选择合理的大小。

示例代码

#include <iostream>
#include <fstream>
#include <vector>

void read_large_file(const std::string& filename) {
    std::ifstream file(filename, std::ios::binary);
    if (!file) {
        std::cerr << "Failed to open file" << std::endl;
        return;
    }

    // 设置一个合适大小的缓冲区,比如 1MB
    std::vector<char> buffer(1024 * 1024);

    while (file.read(buffer.data(), buffer.size())) {
        // 处理读取的数据
        // 可以根据需求处理 buffer
    }

    // 读取剩余的部分
    if (file.gcount() > 0) {
        // 处理剩余的数据
        // 可以根据需求处理 buffer 中的数据
    }

    file.close();
}

4. 内存映射文件 (Memory Mapping)

内存映射文件通过将文件的内容映射到进程的内存空间,可以避免频繁的 I/O 操作,提高文件读取的效率。在大文件处理时,内存映射尤其有用。

  • 缺点
    对于大于10G的文件,当内存不足时会导致读取不全的问题
    该方法不支持长路径,不支持中文路径(本人测试了很多方法,均不成功)
#include <iostream>
#include <fstream>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

void read_large_file(const std::string& filename) {
    int fd = open(filename.c_str(), O_RDONLY);
    if (fd == -1) {
        std::cerr << "Failed to open file" << std::endl;
        return;
    }

    off_t file_size = lseek(fd, 0, SEEK_END);
    lseek(fd, 0, SEEK_SET);

    void* mapped_mem = mmap(nullptr, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (mapped_mem == MAP_FAILED) {
        std::cerr << "Failed to map file to memory" << std::endl;
        close(fd);
        return;
    }

    // 使用映射的内存读取文件内容
    char* file_data = static_cast<char*>(mapped_mem);
    // 可以直接处理 file_data

    // 完成后解除映射
    munmap(mapped_mem, file_size);
    close(fd);
}

http://www.kler.cn/a/446552.html

相关文章:

  • 从监控异常发现网络安全
  • 练习题 最小栈
  • HTTP—03
  • BPMN与一般的流程图区别在那里?
  • C++ 引用的基本用法
  • EE308FZ_Sixth Assignment_Beta Sprint_Sprint Essay 3
  • BenchmarkSQL使用教程
  • object-c 2.0入门笔记
  • srping2.0+升级到spring3.0+遇到的问题,es部分记录一下
  • 详解Linux防火墙-Firewalld原理与实战操作
  • 常用的消息中间件(ActiveMQ、RabbitMQ、RocketMQ、Kafka)面试精华
  • Git(10)之忽略指定文件改动
  • iOS 多个输入框弹出键盘处理
  • 我在华为的安全日常
  • 嵌入式硬件面试题
  • Pycharm和Jupyter Notebook的比较【笔记】
  • 【ETCD】【实操篇(六)】使用多种方式从ETCD集群中读取数据【Get keys by prefix】
  • 《商业模式2.0图鉴》读书笔记(如何构建创新驱动的商业模式:打破定律与重塑价值)
  • 使用Redis实现限流
  • 鸿蒙项目云捐助第十九讲云捐助百度智能名片识别
  • YOLO系列正传(三)神经网络的反向传播(back propagation)与公式推导
  • C语言学习-数组练习
  • OB删除1.5亿数据耗费2小时
  • 开放词汇目标检测(Open-Vocabulary Object Detection, OVOD)综述
  • 《计算机组成及汇编语言原理》阅读笔记:p9-p27
  • 构建MacOS应用小白教程(打包 签名 公证 上架)