简体   繁体   中英

C++ std::ofstream - Move the put pointer

I am writing some data to a file. Occasionally, I want to write a block of data from memory, and then move the put pointer along either 1, 2 or 3 bytes to maintain a 4 byte data boundary format.

I could make a new block of data containing zeros and write this, but this seems unnecessary and clumsy. How can I move the put pointer along 1, 2 or 3 bytes?

I am not sure how to do this, because if I call seekp() surely I will move the pointer outside of the current file size? Whereas I assume ofstream.write() deals with this correctly? ie: It resizes the file somehow while writing data?

I am assuming you are doing something like, except instead of writing two bytes of data you want to write 4 bytes with some padding.

#include <fstream>

using namespace std;

struct data
{
    char first;
    char second;
};

int _tmain(int argc, _TCHAR* argv[])
{
    ofstream outFile;
    data data1;
    data data2;

    data1.first = 'a';
    data1.second = 'b';
    data2.first = 'c';
    data2.second = 'd';

    outFile.open("somefile.dat");

    outFile.write(reinterpret_cast<char*>(&data1), sizeof(data));
    outFile.write(reinterpret_cast<char*>(&data2), sizeof(data));

    outFile.close();

    return 0;
}

One option is to simply make the struct 4 bytes. This could have a disadvantage as it could increase memory footprint.

Using seekp probably is not a good option, I tried it and it sort of worked but not really.

    outFile.write(reinterpret_cast<char*>(&data1), sizeof(data));
    outFile.seekp(2, ios_base::cur);
    outFile.write(reinterpret_cast<char*>(&data2), sizeof(data));
    outFile.seekp(2, ios_base::cur);

This did succeed in adding padding after data1 but not data2. Moving the pointer past the just isn't a good idea as it doesn't change the file size. I tried writing 0 bytes after seekp but this didn't work either.

Honestly I would implement a helper function to provide this functionality. Seems much cleaner this way. Here is a simple example:

#include <fstream>

using namespace std;

struct data
{
    char first;
    char second;
};

void WriteWithPadding(ofstream* outFile, data d, int width);

int _tmain(int argc, _TCHAR* argv[])
{
    ofstream* outFile = new ofstream();
    data data1;
    data data2;

    data1.first = 'a';
    data1.second = 'b';
    data2.first = 'c';
    data2.second = 'd';

    outFile->open("somefile.dat");

    WriteWithPadding(outFile, data1, 4);
    WriteWithPadding(outFile, data1, 4);

    outFile->close();
    delete outFile;

    return 0;
}

void WriteWithPadding(ofstream* outFile, data d, int width)
{
    if (sizeof(d) > width)
        throw;

    width = width - sizeof(d); // width is now amount of padding required
    outFile->write(reinterpret_cast<char*>(&d), sizeof(data));

    // Add Padding
    for (int i = 0; i < width; i++)
    {
        outFile->put(0);
    }
}

Just to be pedantic, I assume you have opened your file with ios::binary , because you'll have issues if you haven't.

When writing a file, the file is only as large as the number of bytes you have written to your file. So if you write three bytes to the file, you will have a three-byte file.

To maintain a four-byte resolution, you must make sure to write four bytes at a time -- if you write a three-byte object, write an additional byte (zero?) to bring it up to four bytes.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM