C++:自定义对象序列化/反序列化失败

发布于 2024-12-25 08:58:44 字数 4121 浏览 1 评论 0原文

我在从存储的文件中读取序列化对象时遇到问题。 (参见下面的代码)。

序列化过程“有效”(尽管可能写得很差),并且因为无法知道用户是否传递了 std::ios::binary 标志,所以我选择不使用 空白。 (它还节省了内存,因为我并没有丢失大量像素数据的潜力。)

我的第一次尝试看起来与示例相同,但 intunsigned char code> 的目的是将下半部分和上半部分位打包到 char 中,然后重新组装它们。

目前,我可以将所有数据读取到文件中,但是当我尝试读取第一段非校验和数据时,它要么返回 0(在尝试使用 char 的情况下),要么返回垃圾(在尝试使用 ints 的情况)

序列化:

std::ostream& operator<<(std::ostream& os, const Sprite& data) {
    int dF = data._dimensions.first;
    int dS = data._dimensions.second;

    int cF = data._center.first;
    int cS = data._center.second;

    int fF = data._frameDimensions.first;
    int fS = data._frameDimensions.second;

    double sF = data._scaleDimensions.first;
    double sS = data._scaleDimensions.second;


    std::string name(*data._file);
    name.shrink_to_fit();
    os << 'S' << 'P' << 'R' << (name.length() + 1) << name.c_str() << dF << dS << cF << cS << fF << fS << sF << sS;
    for(int x = 0; x < data._dimensions.first; ++x) {
        for(int y = 0; y < data._dimensions.second; ++y) {
            int color = getpixel(data._image, x, y);
            os << static_cast<unsigned char>(getr(color)) << static_cast<unsigned char>(getg(color)) << static_cast<unsigned char>(getb(color));
        }
    }
    int tint = data._tint;
    os << static_cast<unsigned char>(getr(tint)) << static_cast<unsigned char>(getg(tint)) << static_cast<unsigned char>(getb(tint));
    os << data._tintIntensity << data._alpha;
    return os;
}

反序列化:

std::istream& operator>>(std::istream& is, Sprite& data) {
    char checksum[3];
    is >> checksum[0] >> checksum[1] >> checksum[2];
    if(checksum[0] != 'S' || checksum[1] != 'P' || checksum[2] != 'R') {
        is.setstate(std::ios::failbit);
        return is;
    }
    int name_length;
    is >> name_length;

    std::string name(name_length, '\0');

    for(int i = 0; i <= name_length; ++i) {
        char current_char = '\0';
        is >> current_char;
        name[i] = current_char;
    }

    int upper = 0;
    int lower = 0;
    is >> upper;
    is >> lower;
    data._dimensions.first = (upper << 8) | lower;

    upper = 0;
    lower = 0;
    is >> upper >> lower;
    data._dimensions.second = ((upper << 8) | lower);

    upper = 0;
    lower = 0;
    is >> upper >> lower;
    data._center.first = ((upper << 8) | lower);

    upper = 0;
    lower = 0;
    is >> upper >> lower;
    data._center.second = ((upper << 8) | lower);

    upper = 0;
    lower = 0;
    is >> upper >> lower;
    data._frameDimensions.first = ((upper << 8) | lower);

    upper = 0;
    lower = 0;
    is >> upper >> lower;
    data._frameDimensions.second = ((upper << 8) | lower);

    double f = 0.0;
    double s = 0.0;
    is >> f >> s;
    data._scaleDimensions.first = f;
    data._scaleDimensions.second = s;

    destroy_bitmap(data._image);
    data._image = NULL;
    data._image = create_bitmap(data._dimensions.first, data._dimensions.second);
    for(int x = 0; x < data._dimensions.first; ++x) {
        for(int y = 0; y < data._dimensions.second; ++y) {
            unsigned char r = 0;
            unsigned char g = 0;
            unsigned char b = 0;
            is >> r >> g >> b;
            int color = ((r << 16)  | (g << 8) | b); //0xRRGGBB
            putpixel(data._image, x, y, color);
        }
    }
    unsigned char rtint = 0;
    unsigned char gtint = 0;
    unsigned char btint = 0;
    is >> rtint >> gtint >> btint;
    data._tint = ((rtint << 16)  | (gtint << 8) | btint); //0xRRGGBB

    is >> data._tintIntensity;
    is >> data._alpha;
    return is;
}

I'm having problems reading a serializaed object back from its stored file. (See code below).

The serialization process "works", (albeit, probably written very poorly), and because there is no way of knowing whether the user is passing a std::ios::binary flag or not I opted NOT to use formatted output with whitespace. (It also saves on memory as the potential for massive amounts of pixel data was not lost on me.)

My first attempt looked the same as the sample but the ints were unsigned chars with the intent of bit-packing the lower and upper halves into chars and later reassembling them.

Currently I can read all data to a file but when I attempt to read the first piece of non-checksum data it either returned 0 (in the case of the attempt with the chars) or garbage (in the case of the attempt with the ints)

Serialization:

std::ostream& operator<<(std::ostream& os, const Sprite& data) {
    int dF = data._dimensions.first;
    int dS = data._dimensions.second;

    int cF = data._center.first;
    int cS = data._center.second;

    int fF = data._frameDimensions.first;
    int fS = data._frameDimensions.second;

    double sF = data._scaleDimensions.first;
    double sS = data._scaleDimensions.second;


    std::string name(*data._file);
    name.shrink_to_fit();
    os << 'S' << 'P' << 'R' << (name.length() + 1) << name.c_str() << dF << dS << cF << cS << fF << fS << sF << sS;
    for(int x = 0; x < data._dimensions.first; ++x) {
        for(int y = 0; y < data._dimensions.second; ++y) {
            int color = getpixel(data._image, x, y);
            os << static_cast<unsigned char>(getr(color)) << static_cast<unsigned char>(getg(color)) << static_cast<unsigned char>(getb(color));
        }
    }
    int tint = data._tint;
    os << static_cast<unsigned char>(getr(tint)) << static_cast<unsigned char>(getg(tint)) << static_cast<unsigned char>(getb(tint));
    os << data._tintIntensity << data._alpha;
    return os;
}

Deserialization:

std::istream& operator>>(std::istream& is, Sprite& data) {
    char checksum[3];
    is >> checksum[0] >> checksum[1] >> checksum[2];
    if(checksum[0] != 'S' || checksum[1] != 'P' || checksum[2] != 'R') {
        is.setstate(std::ios::failbit);
        return is;
    }
    int name_length;
    is >> name_length;

    std::string name(name_length, '\0');

    for(int i = 0; i <= name_length; ++i) {
        char current_char = '\0';
        is >> current_char;
        name[i] = current_char;
    }

    int upper = 0;
    int lower = 0;
    is >> upper;
    is >> lower;
    data._dimensions.first = (upper << 8) | lower;

    upper = 0;
    lower = 0;
    is >> upper >> lower;
    data._dimensions.second = ((upper << 8) | lower);

    upper = 0;
    lower = 0;
    is >> upper >> lower;
    data._center.first = ((upper << 8) | lower);

    upper = 0;
    lower = 0;
    is >> upper >> lower;
    data._center.second = ((upper << 8) | lower);

    upper = 0;
    lower = 0;
    is >> upper >> lower;
    data._frameDimensions.first = ((upper << 8) | lower);

    upper = 0;
    lower = 0;
    is >> upper >> lower;
    data._frameDimensions.second = ((upper << 8) | lower);

    double f = 0.0;
    double s = 0.0;
    is >> f >> s;
    data._scaleDimensions.first = f;
    data._scaleDimensions.second = s;

    destroy_bitmap(data._image);
    data._image = NULL;
    data._image = create_bitmap(data._dimensions.first, data._dimensions.second);
    for(int x = 0; x < data._dimensions.first; ++x) {
        for(int y = 0; y < data._dimensions.second; ++y) {
            unsigned char r = 0;
            unsigned char g = 0;
            unsigned char b = 0;
            is >> r >> g >> b;
            int color = ((r << 16)  | (g << 8) | b); //0xRRGGBB
            putpixel(data._image, x, y, color);
        }
    }
    unsigned char rtint = 0;
    unsigned char gtint = 0;
    unsigned char btint = 0;
    is >> rtint >> gtint >> btint;
    data._tint = ((rtint << 16)  | (gtint << 8) | btint); //0xRRGGBB

    is >> data._tintIntensity;
    is >> data._alpha;
    return is;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夕嗳→ 2025-01-01 08:58:44

反序列化不应该是这样的:

int upper = 0;
int lower = 0;
is >> upper;
is >> lower;
data._dimensions.first = upper;
data._dimensions.second = lower;

中心和框架尺寸类似

shouldn't deserialization be something like this:

int upper = 0;
int lower = 0;
is >> upper;
is >> lower;
data._dimensions.first = upper;
data._dimensions.second = lower;

and similar for center, and frameDimensions

回忆躺在深渊里 2025-01-01 08:58:44

我会使用bitfileds。只是不要忘记在之前添加 #pragma pack(1) 和之后添加 #pragma pack()。由于计算机只能寻址字节,因此您必须确保位字段是 8 的倍数。此外,位的打包取决于编译器/机器,因此您的阅读器应该使用相同的编译器进行编译。
然后只需使用例如:

somefilestream.write(&some_bitfield_struct, sizeof(some_bitfield_struct));

I would use bitfileds. Just don't forget to add #pragma pack(1) before and #pragma pack() after. Since the computer can only address bytes, you have to make sure your bit-fields are the multiple of 8. Also the packing of bits is compiler/machine dependent, so your reader should be compiled with the same compiler.
Then just use for example:

somefilestream.write(&some_bitfield_struct, sizeof(some_bitfield_struct));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文