Write and read binary files with date

closed account (Nw54LyTq)
...
Last edited on
It's not clear what you want to write in the file. Is pchName a null terminated string? I'll presume you are for the rest of this post. I'll also assume C++ rather than C.

If you're reading/writing on a binary stream, you need to pass the content start and length. In your case, you calculate the length (using strlen), and write that. But when you come around to reading it, how do you know the length?

One way is to write the length in the first four bytes, then write the data.

And finally, if you're using C++, use a string class to hold a string and don't use char arrays. It'll preserve your sanity.

Let's say we have a binary file of variable length strings encoded in this way ... I've used ANSI C's file handling rather than C++ iostreams because that's what you presented in your question:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
bool append(std::string filename, std::string content)
{
    if (FILE* f = fopen(filename.c_str(), "ab"))
    {
        uint32_t len = hton(content.size());
        fwrite(&len, sizeof(len), 1, f);
        fwrite(content.c_str(), len, 1, f);
        fclose(f);
        return true; 
    }

    return false;
}

bool append(std::string filename, const char* content)
{
    append(filename, std::string(content));
}

std::vector<std::string> fetch(std::string filename)
{
    std::vector<std::string> out;

    if (FILE* f = fopen(filename.c_str(), "rb"))
    {
        // read each string and append to out
        while (!feof(f))
        {
            uint32_t len;
            fread(&len, sizeof(len), 1, f);
            len = ntohl(len);
            std::unique_ptr<char[]> buf(new char[len]);
            fread(buf, len, 1, f);
            out.emplace_back(buf, len);
        }
        fclose(f);
    }

    return out;
}
Last edited on
if you want to quickly find and update records in a binary file, it really, really helps your efficiency to have all the records the same size. So if you can put a max length on your string data, write the string and pad out with zeros, that is a solid approach. You can still use standard sting, but youll manually pad the file data.

If you don't need this functionality, length folowed by data works great too, but you can't just jump a multiple/byte offset into the file based off record size anymore.

closed account (Nw54LyTq)
Ok but without const char * will not let me continue. Is part of another code. Do you have another way?
Its in his code already once, but you can take a c string from a c++ string:
const char * cp = content.c_str();
closed account (Nw54LyTq)
...
Last edited on
What is the purpose of the following line?
if (pchName != NULL && remove(pchName))

How and where is pchName defined and initialized?

Also: fwrite(pchName, 1, file_data[0] * sizeof(unsigned char), file1);, where is file_data[0] initialized when the else clause is executed?


Topic archived. No new replies allowed.