The best way to read an entire file opened in text mode into a string variable

This is what I cannot change:

  • C ++ language
  • However, the file is opened using the old old fopen()
  • File does not open in binary mode

This is what I have to do:

  • Write a function that loads the entire file into std::string. Lines should be split only \n, not other options.

This is what I did:

string ReadWhole()
{
    Seek(0);
    char *data = new char[GetSize()];

    if (1 != fread(data, GetSize(), 1, mFile))
        FATAL(Text::Format("Read error: {0}", strerror(errno)));

    string ret(data, GetSize());
    delete[] data;
    return ret;
}

For reference, this is GetSize, but it just returns the file size (cached):

int GetSize()
{
    if (mFileSize)
        return mFileSize;

    const int current_position = ftell(mFile);
    fseek(mFile, 0, SEEK_END);
    mFileSize = ftell(mFile);
    fseek(mFile, current_position, SEEK_SET);

    return mFileSize;
}

This is problem

fread()fails because the file has line endings \r\nand they are considered only 1 character instead of 2, so it tries to read more than the characters in the file.

I could fix this with help fgets, but I was wondering if there is a better way. Thank.

+5
4

fread , , ferror(mFile). 0 (false), fread , . , :

size_t number_of_bytes_read = fread(data, 1, GetSize(), mFile);
+3

, .

#include <string>
#include <fstream>
#include <sstream>
std::string load_file ( const std::string& path ) 
{
    std::ostringstream contents;
    std::ifstream file(path);
    if ( !file.is_open() ) {
        // process error.
    }
    contents << file.rdbuf();
    return (contents.str());
}

: ( ) . () , . std::istream, , , (.. ).

: FILE*, , std::streambuf, FILE* std::istream std::ostream.

fooobar.com/questions/100437/....

P.S.. , , , .

#include <string>
#include <istream>
#include <sstream>
#include "FILEbuf.h"
std::string load_file ( ::FILE * opened_c_file ) 
{
    FILEbuf buffer(opened_c_file);
    std::istream file(&buffer);
    std::ostringstream contents;
    contents << file.rdbuf();
    return (contents.str());
}
+2

You can select a buffer of a fixed size and re- freadnothing more from the file and add it to the line with string::apeend(char*, size_type).

0
source

Just use fgetc()to read one character at a time. You can use a special case to convert the endings' \ r \ n 'to regular' \ n.

std::string ReadWhole() {
    std::string ret;
    char prev = 0, c;
    while ((c = fgetc(mFile)) != EOF) {
        if (prev == '\r' && c == '\n') {
            ret.erase(ret.rend()); // erase the previous \r
        }
        ret += c;
        prev = c;
    }
    return ret;
}
0
source

All Articles