简体   繁体   中英

When writing into a binary file, `std::ofstream::write` sometimes writes more bytes than it should

I'm trying to write a 3D geometry into a binary STL file. Here is how the main program works:

ParseSTL stl();
//generate the 3D model
std::string outfname = "test.stl";
std::ofstream outf(outfname, std::ios_base::out & std::ios_base::binary);
stl.writeBinarySTL(outf);

and the STL writer is:

void writeBinarySTL(std::ofstream &outf)
{
    char attr[2] = { 0 };
    char header[80] = { 0 };
    int count = 0;
    outf.write(header, 80);
    //count += 80;
    //std::cout << "after header: file position: " << outf.tellp() << "  bytes written: " << count << "\n";
    //if ((int)outf.tellp() != count)
    //    std::cout << "something is wrong!\n";
    outf.write(reinterpret_cast<char *>(&facecount), sizeof(int));
    //count += sizeof(int);
    //std::cout << "after number of faces: file position: " << outf.tellp() << "  bytes written: " << count << "\n";
    //if ((int)outf.tellp() != count)
    //    std::cout << "something is wrong!\n";
    for (int i = 0; i < facecount; i++)
    {
        struct face{
            float n[3];
            float v[3][3];
        } f;
        for (int j = 0; j < 3; ++j)
            f.n[j] = (float) normals[i][j];
        for (int j = 0; j < 3; ++j)
            for (int k = 0; k < 3; ++k)
                f.v[j][k] = (float)vertices[faces[i][j]][k];
        outf.write(reinterpret_cast<char *>(&f), sizeof(f));
        //count += sizeof(f);
        //std::cout << "after struct: file position: " << outf.tellp() << "  bytes written: " << count << "\n";
        //if ((int)outf.tellp() != count)
        //{
        //    std::cout << "something is wrong!\n";
        //    break;
        //}
        outf.write(attr, 2);
        //count += 2;
        //std::cout << "after attributes: file position: " << outf.tellp() << "  bytes written: " << count << "\n";
        //if ((int)outf.tellp() != count)
        //{
        //    std::cout << "something is wrong!\n";
        //    break;
        //}
    }
    //std::cout << "Bytes written: " << count << "\n";
}

The commented parts are just for debugging, and facecount is a member of the class ParseSTL that stores number of triangles, normals is a vector of 3D vectors that stores normals for all faces, vertices is a vector of 3D vectors that stores coordinates for all vertices, and faces is a vector of 3 integers that stores the index of vrtices that belong to a triangle. Now, if I run the program, here is the output that I get:

Vertex count = 4243
Face count = 3168
Edge count = 0
after header: file position: 80  bytes written: 80
after number of faces: file position: 84  bytes written: 84
after struct: file position: 132  bytes written: 132
after attributes: file position: 134  bytes written: 134
...
after struct: file position: 532  bytes written: 532
after attributes: file position: 534  bytes written: 534
after struct: file position: 583  bytes written: 582
something is wrong!

So, it seems that the line outf.write(reinterpret_cast<char *>(&f), sizeof(f)); is writing 1 more byte than it should. This drifting happens once in a while, and at the end, instead of a file that is 158,484 Bytes, I'm getting a file that is 158,896 Bytes. If I add a outf.seekp(count) after writing the struct, the final file size is correct, but some of the floats are not written correctly (so the drift is not always at the end of the struct).

I was wondering what I'm doing wrong that causes this extra Bytes to be written into the file. Oh, and I'm using Microsoft Visual Stusio Express 2013.

This line

std::ofstream outf(outfname, std::ios_base::out & std::ios_base::binary);

needs to be

std::ofstream outf(outfname, std::ios_base::out | std::ios_base::binary);
                                              ^^^^^ The difference

It can be simplified by omitting the std::ios_base::out flag (Thanks @Blastfurnace for the hint). It also reduces the chances of such errors creeping in.

std::ofstream outf(outfname, std::ios_base::binary);

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