C++ Get all bytes of a file in to a char array?

后端 未结 3 1675
礼貌的吻别
礼貌的吻别 2020-12-03 12:32

Given:

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

How do I read the chars of the file in to the above buffer? I have

相关标签:
3条回答
  • 2020-12-03 12:55

    Most of the time they are right about getline, but when you want to grab the file 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

    NOTE: seekg and tellg to get the size of the file falls into the category of "usually works". This is not guaranteed. tellg only promises a number that can be used to return to a particular point. That said,

    Note: The file was not opened in binary mode. There can be some behind-the-scenes character translations, for example the Windows newline of \r\n being converted to the \n used by C++. length can be greater than the number of characters ultimately placed in buffer.

    2019 rethink

    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.
    

    If you're looping on buffered reads until you consume the whole file you'll want some extra smarts to catch that.

    If you want to read the whole file in one shot and can afford to use resizable buffers, take the advice in Remy Lebeau's answer.

    0 讨论(0)
  • 2020-12-03 12:58

    Another option would be to use a std::vector for the buffer, then use a std::istreambuf_iterator to read from an std::ifstream directly into the std::vector, eg:

    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>() );
    

    Alternatively:

    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) );
    

    If you go with @user4581301's solution, I would still suggest using std::vector for the buffer, at least:

    //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);
    }
    
    0 讨论(0)
  • 2020-12-03 13:02

    If you're concerned with efficiency (you rejected getline()) then a C-style mmap is probably best:

    #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);
    
    0 讨论(0)
提交回复
热议问题