Home > OS >  fread() and fwrite() using strings
fread() and fwrite() using strings

Time:12-03

I'm trying to implement simple fread() and frwite() example using strings. The program gives me segfault or free(): invalid pointer errors. Below is the example code I'm working with.

#include <fstream>
#include <iostream>

static bool file_read(FILE* file) {
    std::string value="abcd";
    std::string retrieved;
    size_t read, write;
    write = fwrite(&value, sizeof(value), 1, file);
    fseek(file, 0, SEEK_SET);
    read = fread(&retrieved, sizeof(value), 1, file);
    return true;
}

int main(int argc, char *argv[]) {
    FILE *file = NULL;
    file = fopen("file_test", "wb ");
    file_read(file);
    fclose(file);
}

I checked if file is opened correctly and that retrieved has the same value as value. I don't think I'm freeing any variables in my code. I'm suspecting that fread is causing all the trouble.

fread(&retrieved[0], sizeof(char), 4, file)

Doesn't read the value to retrieved and was where I am doing wrong.

CodePudding user response:

if you want to access the actual character buffer inside std::string you need to use value.c_str()

the length of the string is not given by sizeof, use value.length()

you cannot read from a file directly into a std::string using fread. You must read it into an intermediate char [] buffer and load from there. Or use ifstream

CodePudding user response:

std::string is not a trivial type. It contains several private data members, including a pointer to character data that may reside in memory that is outside of the string object. So you can't read/write the raw bytes of the string object itself, like you are trying to do. You need to instead serialize its character data separately, eg:

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

static bool file_writeStr(std::FILE* file, const std::string &value) {
    size_t len = value.size();
    bool res = (std::fwrite(reinterpret_cast<char*>(&len), sizeof(len), 1, file) == 1);
    if (res) res = (std::fwrite(value.c_str(), len, 1, file) == 1);
    return res;
}

static bool file_readStr(std::FILE* file, std::string &value) {
    size_t len;
    value.clear();
    bool res = (std::fread(reinterpret_cast<char*>(&len), sizeof(len), 1, file) == 1);
    if (res && len > 0) {
        value.resize(len);
        res = (std::fread(&value[0], len, 1, file) == 1);
    }
    return res;
}

static bool file_test(std::FILE* file) {
    std::string value = "abcd";
    std::string retrieved;
    bool res = file_writeStr(file, value);
    if (res) {
        std::fseek(file, 0, SEEK_SET);
        res = file_readStr(file, retrieved);
    }
    return res;
}

int main() {
    std::FILE *file = std::fopen("file_test", "wb ");
    if (file_test(file))
        std::cout << "success";
    else
        std::cerr << "failed";
    std::fclose(file);
}
  • Related