Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

TrommlBomml

Community-Fossil

  • »TrommlBomml« ist der Autor dieses Themas

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

1

17.07.2016, 15:34

[GELÖST] C++ lesen von Binärdatei liefert falsche Werte

Hi zusammen,

ich merke, mein C++ ist etwas eingerostet. Vielleicht habt ihr eine Idee:

Ich öffne eine Datei mit ifstream und lese binär mit ifstream::read(). Ich habe mir eine kleine Wrapperklasse gebaut, die ein paar Methoden anbietet, mir aus dem Binärstream typisierte Daten zu lesen, weil mir das Arbeit erspart. Ich lese bisher byte (char), int (32-bit), string (ascii mit vorgegebener Länge) und float. Die Klasse hat eine Referenz auf den ifstream im Konstruktor.

Wenn ich lese, habe ich mit Debugger herausgefunden, dass ein Wert, den ich als byte lese, keinen sinnvollen Wert liefert (-74). Das merke ich, weil das programm sehr lange dauert und ich dann auf pause drücke und mir den Wert anschaue (siehe Code). Wenn ich allerdings denselben Code mit einem Breakpoint vor dem Fehler debugge, steht der richtige Wert drin. Das passiert alles schon beim ersten durchlauf der iterationen in den for-schleifen. Ich arbeite mit Visual Studio 2015. Dazu habe ich parallel noch ein tinyxml2-Dokument offen, welches Daten aus den Binärdaten erzeugt (den habe ich gekürzt, weil der nur stört). Hier der Code:

C-/C++-Quelltext

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
41
42
43
#include "MemoryStream.h"
#include <iterator>
#include <sstream>
#include <Windows.h>

MemoryStream::MemoryStream(std::ifstream& stream):
    _stream(stream)
{
}

MemoryStream::~MemoryStream()
{
}

char MemoryStream::ReadByte()
{
    char value;
    _stream.read(&value, 1);
    return (int)value;
}

std::string MemoryStream::ReadString(int length)
{
    char *data = new char[length];
    _stream.read(data, length);
    std::string value(data, length);
    delete[] data;
    return value;
}

int MemoryStream::ReadInteger()
{
    int value;
    _stream.read(reinterpret_cast<char*>(&value), sizeof(int));
    return value;
}

float MemoryStream::ReadFloat()
{
    float value;
    _stream.read(reinterpret_cast<char*>(&value), sizeof(float));
    return value;
}


Bitte nicht über den Namen wundern, ursprünglich hatte ich die ganze datei in einen Vektor gespeichert und bin dann über die Probleme gestolpert. Daher hab ich das gerade umgebaut, dass die Dateien direkt gelesen werden, um ggf. Byteorder Probleme auszuschließen.

ich habe den code etwas gekürzt, damit es nicht so viel ist. Siehe kommentar, wo der falsche Wert steht:

C-/C++-Quelltext

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>

#include "MemoryStream.h"
#include "tinyxml2.h"

const unsigned char ENTITYTYPE_SOLID_DRAWN = 0;
const unsigned char ENTITYTPE_TRANSPARENT_DRAWN = 1;
const unsigned char ENTITYTYPE_SOLID_NOTDRAWN = 2;
const unsigned char ENTITYTYPE_SCREEN = 3;
const unsigned char ENTITYTYPE_WAYPOINT = 4;
const unsigned char ENTITYTYPE_LIGHT = 5;
const unsigned char ENTITYTYPE_SPOTLIGHT = 6;
const unsigned char ENTITYTYPE_SOUNDEMITTER = 7;

void InsertDrawableEntity(tinyxml2::XMLElement *entityElement, MemoryStream& memoryStream)
{
    auto meshCount = memoryStream.ReadByte();
    for (auto i = 0; i < meshCount; i++)
    {

        auto blendType = 0;
        auto texture0 = 0;
        auto texture1 = 0;

        auto texturesToUseMask = memoryStream.ReadByte();  //Hier wird -74 an statt 2 geliefert! das führt dann zu folgefehlern.
        if (texturesToUseMask & 1)
        {
            texture0 = memoryStream.ReadByte();
        }
        if (texturesToUseMask & 2)
        {
            texture1 = memoryStream.ReadByte();
        }
        
        //gekürzt ....
    }
}

int main()
{
    std::ifstream r2file("008_opt.rm2", std::ios::binary);
    if (!r2file.is_open())
    {
        std::cout << "could not open file!";
        std::cin.get();
        return 0;
    }

    MemoryStream memoryStream(r2file);

    auto magicPackage = memoryStream.ReadString(3);

    if (magicPackage != "RM2")
    {
        std::cout << "invalid file format";
        std::cin.get();
        return 0;
    }

    auto textureCount = memoryStream.ReadByte();
    for (auto i = 0; i < textureCount; i++)
    {
        int textureNameLength = memoryStream.ReadByte();
        auto texture = memoryStream.ReadString(textureNameLength);
        auto alpha = memoryStream.ReadByte();
    }

    int entAmount = memoryStream.ReadByte();

    for (auto i = 0; i < entAmount; i++)
    {
        auto entityType = memoryStream.ReadByte();

        switch (entityType)
        {
        case ENTITYTYPE_SOLID_DRAWN:
        case ENTITYTPE_TRANSPARENT_DRAWN:
            InsertDrawableEntity(entityElement, memoryStream);
            break;
        }
    }

    document.SaveFile("008_opt008_opt.xml");

    return 0;
}

TrommlBomml

Community-Fossil

  • »TrommlBomml« ist der Autor dieses Themas

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

2

17.07.2016, 15:48

Mäh, vergesst es. Ich hab den Fehler nun doch gefunden...Ich hab nur vergessen was zu lesen, ein index übersehen, das es doch im zweiten durchlauf im Mesh war.

Sorry! Bitte schließen.