【问题标题】:C++ Get all bytes of a file in to a char array?C ++将文件的所有字节放入char数组中?
【发布时间】:2016-04-16 00:14:57
【问题描述】:

给定:

const string inputFile = "C:\MyFile.csv";
char buffer[10000];

如何将文件的字符读入上述缓冲区?我一直在网上四处寻找,但似乎没有一个答案有效。他们都希望调用 getline()。

【问题讨论】:

    标签: c++


    【解决方案1】:

    注意:Remy Lebeau's answer 开头。对于一般的文件读取,这是完成这项工作的艰难方法;它更符合此特定提问者的特定需求,但不一定能满足您的需求以及 std::vectorstd::istreambuf_iterator 方法。


    大多数时候他们对getline 的看法是正确的,但是当您想要获取文件时as a stream of bytes, you want ifstream::read()

    //open file
    std::ifstream infile("C:\\MyFile.csv");
    
    //get length of file
    infile.seekg(0, std::ios::end);
    size_t length = infile.tellg();
    infile.seekg(0, std::ios::beg);
    
    // don't overflow the buffer!
    if (length > sizeof (buffer))
    {
        length = sizeof (buffer);
    }
    
    //read file
    infile.read(buffer, length);
    

    Docs for ifstream::seekg()

    Docs for ifstream::tellg()

    注意:seekg()tellg() 获取文件大小属于“通常有效”的类别。这不能保证。 tellg() 只承诺一个可用于返回特定点的数字。那就是……

    注意:该文件不是以二进制模式打开的。可能有一些幕后字符翻译,例如 \r\n 的 Windows 换行符被转换为 C++ 使用的 \nlength 可以大于最终放入 buffer 的字符数。

    2019 年重新思考

    size_t chars_read;
    //read file
    if (!(infile.read(buffer, sizeof(buffer)))) // read up to the size of the buffer
    {
        if (!infile.eof()) // end of file is an expected condition here and not worth 
                           // clearing. What else are you going to read?
        {
            // something went wrong while reading. Find out what and handle.
        }
    }
    chars_read = infile.gcount(); // get amount of characters really read.
    

    如果您在使用整个文件之前循环缓冲读取,则需要一些额外的智能来捕捉它。

    如果您想一次性读取整个文件,并且有能力使用可调整大小的缓冲区,请采纳Remy Lebeau's answer 中的建议。

    【讨论】:

    • 根据doc,我认为你应该使用ifstream::endifstream::beg而不是ifs::endifs::beg
    • @tjysdsg 在这里无关紧要,但值得遵循的建议。使用静态成员获得的优势,尤其是一直回到 ios 的好处是,您可以更改流的标识符和类型,而不必进行太多重构。零成本的通用代码几乎总是比特定代码更好。我还需要清理一些其他问题。
    【解决方案2】:

    另一种选择是使用std::vector 作为缓冲区,然后使用std::istreambuf_iteratorstd::ifstream 直接读取std::vector,例如:

    const std::string inputFile = "C:\\MyFile.csv";
    std::ifstream infile(inputFile, std::ios_base::binary);
    
    std::vector<char> buffer( std::istreambuf_iterator<char>(infile),
                              std::istreambuf_iterator<char>() );
    

    或者:

    const std::string inputFile = "C:\\MyFile.csv";
    std::ifstream inFile(inputFile, std::ios_base::binary);
    
    inFile.seekg(0, std::ios_base::end);
    size_t length = inFile.tellg();
    inFile.seekg(0, std::ios_base::beg);
    
    std::vector<char> buffer;
    buffer.reserve(length);
    std::copy( std::istreambuf_iterator<char>(inFile),
               std::istreambuf_iterator<char>(),
               std::back_inserter(buffer) );
    

    如果您使用@user4581301 的解决方案,我仍然建议使用std::vector 作为缓冲区,至少:

    //open file
    std::ifstream infile("C:\\MyFile.csv");
    std::vector<char> buffer;
    
    //get length of file
    infile.seekg(0, infile.end);
    size_t length = infile.tellg();
    infile.seekg(0, infile.beg);
    
    //read file
    if (length > 0) {
        buffer.resize(length);    
        infile.read(&buffer[0], length);
    }
    

    【讨论】:

      【解决方案3】:

      如果您关心效率(您拒绝了 getline()),那么 C 风格的 mmap 可能是最好的:

      #include <sys/stat.h>
      #include <sys/mman.h>
      
      struct stat s;
      stat(inputFile.c_str(), &s);
      size_t file_size = st.st_size;
      
      int fhand = open(inputFile);
      char* file_buf = (char*)mmap(0, file_size, PROT_READ, MAP_FILE|MAP_PRIVATE, fhand, 0);
      ...
      munmap(file_buf, file_size);
      

      【讨论】:

      • 或者,在没有mmap()的Windows上,您可以使用CreateFile()CreateFileMapping()MapViewOfFile()来完成同样的事情。
      猜你喜欢
      • 1970-01-01
      • 2015-07-11
      • 1970-01-01
      • 2018-12-11
      • 1970-01-01
      • 2011-08-01
      • 2013-07-19
      • 1970-01-01
      • 2011-06-16
      相关资源
      最近更新 更多