Seite 1 von 1

[gelöst] Problem mit char und QFile::read, Wert falsch

Verfasst: 24. März 2010 19:18
von Hol_den_Wagen
Hallo,

Habe mal wieder ein kleines Problemchen und komm nicht drauf.
Ich lese mit QIODevice::readData ( char * data, qint64 maxSize ) einige Bytes in ein char-Array ein.

Code: Alles auswählen

char *temp;
temp = new char[resX * resY];

videoFile = new QFile(path);
if (!videoFile->open(QIODevice::ReadOnly)) {
    return;
}

videoFile->read(temp, resX * resY);
Wenn ich mein File in einem Hex-Editor öffne, werden mir für die ersten 16 Bytes folgende Werte angezeigt:
0a 28 c9 ff f7 fe fe fe fe fe fe fe fe fe fe fe

wenn ich die ersten 16 Bytes meines char-Arrays ausgebe

Code: Alles auswählen

for (j = 0; j < 16; j++) {
    qDebug("temp[%i] = %x", j, temp[j]);
}
erhalte ich folgende Ausgabe:
temp[0] = a
temp[1] = 28
temp[2] = ffffffc9
temp[3] = ffffffff
temp[4] = fffffff7
temp[5] = fffffffe
temp[6] = fffffffe
temp[7] = fffffffe
temp[8] = fffffffe
temp[9] = fffffffe
temp[10] = fffffffe
temp[11] = fffffffe
temp[12] = fffffffe
temp[13] = fffffffe
temp[14] = fffffffe
temp[15] = fffffffe

Die ersten beiden Werte stimmen dabei mit denen die mir der Hex-Editor liefert überein. Aber ab dann ändert sich das. Wenn man beispielsweise den dritte Wert betrachtet: der Hex-Editor sagt c9, was dezimal 201 entspricht. Die Ausgabe meines Programms sagt ffffffc9. Mein Taschenrechner spuckt mir für die dezimalzahl -55 (= 201 - 256) ebenfalls den Hex-Wert ffffffc9 aus. Dies gilt genauso für alle weiteren Werte meines char-Arrays.

Woran könnte dies liegen? Was passiert hier?

Vielen Dank und viele Grüße,
HdW

Verfasst: 24. März 2010 19:22
von kater
In einem Char passen nur 128 rein (oder waren es 127?) Versuch es doch mal mit unsigned char.

Verfasst: 24. März 2010 19:26
von Hol_den_Wagen
dann liefert der compiler leider:

error C2664: 'qint64 QIODevice::read(char *,qint64)' : cannot convert parameter 1 from 'unsigned char *' to 'char *'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

Verfasst: 25. März 2010 08:32
von kater
Ajo jetzt nimmst du deine Augen und liest die Fehlermeldung. Also nachlesen wie ein cast geht. Ich weiss es nämlich auch nicht =)

Verfasst: 25. März 2010 10:16
von archer
Das was du einliest ist schon richtig,
nur werden in deiner for-Schleife die Werte wohl in 32-bit-Werte gecastet und dann als String angezeigt.
Wenn die Zahl negativ ist, sethen halt vorne die ff.. .

Verfasst: 25. März 2010 10:31
von RHBaum
@Hol_den_Wagen

Qt ist ne C++ lib!

Code: Alles auswählen

temp = new char[resX * resY];
Statt rohe dynamische Arrays (fehleranfaellig, exceptionsicherheit) solltest echt in erwaegung ziehen, Array Klassen zu verwenden. Dafuer gibts dann auch komfortablere methoden.
passende Containerklassen waeren:
QByteArray, QVector<char>, std::vector<char>

Es sei denn du bestehst auf eigene dyn. allokierung wegens Übungszwecken.
Also nachlesen wie ein cast geht. Ich weiss es nämlich auch nicht =)
Und bevor du wieder in die C-Welt verfaellst ... (char *) ist pfui !!!
C++ technisch richtiger:

Code: Alles auswählen

unsigned char *temp;
temp = new unsigned char[resX * resY];

videoFile = new QFile(path);
if (!videoFile->open(QIODevice::ReadOnly)) {
    return;
}

videoFile->read(reinterpret_cast<char *>(temp), resX * resY);
Aber Besser :

Code: Alles auswählen


/// Statt selber dynamisch speicher verwalten, dass spezialisierten klassen machen lassen
/// Und auch gleich die richtige Groesse koennen wir erzeugen lassen, wenn wir sie wissen.
QByteArray tempBuffer(resX * resY,0);

videoFile = new QFile(path);
if (!videoFile->open(QIODevice::ReadOnly)) {
    return;
}

videoFile->read(tempBuffer.data(),tempBuffer.size());
Da nur das Dyn Array ausgetauscht, damit siehst wie man sowas eleminiert ohne grossartig code zu veraendern. Aber es geht noch komfortabler, weil QIODevice gleich ByteArrays erzeugen kann

Code: Alles auswählen

// videoFile = new QFile(path); warum dynamisch erzeugen ? LifeTime Problem ? Besser: 
QFile videoFile(path);
if (!videoFile.open(QIODevice::ReadOnly)) return;

QByteArray tempBuffer = videoFile.read(resX * resY);
wie kommt man nu auf die einzelnen Zeichen im ByteArray als unsigned chars (zur besseren darstellung) ?
Richtig:
unsigned char MyChar = static_cast<unsigned char>(tempBuffer.at(x));
wichtig: at() statt [] damit du ne exception kriegst falls x >= tempBuffer.size() !

Ciao ...

Verfasst: 25. März 2010 14:21
von Hol_den_Wagen
Hab ich wieder was dazugelernt :-) Super, vielen Dank für die freundliche Hilfe!

LG, HdW

Verfasst: 25. März 2010 17:59
von kater
Auch ich bedankte ich für das tolle Beispiel. Aber noch eine Frage hinterher. Gibt es keinen Weg aus einem QByteArr ein char zu bekommen ohne zu casten?

Verfasst: 25. März 2010 18:02
von TSS
Die Funktion at() der Klasse QByteArray gibt dir einen char zurück. Gecastet wurde dieser dann in einen unsigned char.