Coderino Javarino
Coderino Javarino

Reputation: 2881

Data Input Stream reads different than desired int value

I am trying to read from .dem (counter-strike demo files) files using DataInputStream. So far I know that it starts with a header, and in C it looks like this (https://github.com/csgo-data/demoinfogo-linux/blob/master/src/demofile.h)

struct demoheader_t
{
    char    demofilestamp[ 8 ];             // Should be HL2DEMO
    int32   demoprotocol;                   // Should be DEMO_PROTOCOL
    int32   networkprotocol;                // Should be PROTOCOL_VERSION
    char    servername[ MAX_OSPATH ];       // Name of server
    char    clientname[ MAX_OSPATH ];       // Name of client who recorded the game
    char    mapname[ MAX_OSPATH ];          // Name of map
    char    gamedirectory[ MAX_OSPATH ];    // Name of game directory (com_gamedir)
    float   playback_time;                  // Time of track
    int32   playback_ticks;                 // # of ticks in track
    int32   playback_frames;                // # of frames in track
    int32   signonlength;                   // length of sigondata in bytes
};

, and this is my header class, which is responsible for reading it from stream:

package cropper;

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintStream;

import static cropper.Cropper.*;

public class DemoHeader {

    private final static int MAX_OSPATH = 260;
    private final static int STAMP_L = 8;

    char    demofilestamp[];                // Should be HL2DEMO
    int demoprotocol;                   // Should be DEMO_PROTOCOL
    int networkprotocol;                // Should be PROTOCOL_VERSION
    char    servername[];       // Name of server
    char    clientname[];       // Name of client who recorded the game
    char    mapname[];          // Name of map
    char    gamedirectory[];    // Name of game directory (com_gamedir)
    float   playback_time;                  // Time of track
    int   playback_ticks;                   // # of ticks in track
    int   playback_frames;              // # of frames in track
    int signonlength;                   // length of sigondata in bytes

    private DemoHeader(){
        demofilestamp = new char[STAMP_L];
        servername = new char[MAX_OSPATH];
        clientname = new char[MAX_OSPATH];
        mapname = new char[MAX_OSPATH];
        gamedirectory = new char[MAX_OSPATH];
    }

    public static DemoHeader getHeader(DataInputStream dis) throws IOException{
        DemoHeader header = new DemoHeader();
        for (int i = 0; i < header.demofilestamp.length; header.demofilestamp[i++] = (char) dis.readByte());
        header.demoprotocol = dis.readInt();
        header.networkprotocol = dis.readInt();
        for (int i = 0; i < header.servername.length; header.servername[i++] = (char) dis.readByte());
        for (int i = 0; i < header.clientname.length; header.clientname[i++] = (char) dis.readByte());
        for (int i = 0; i < header.mapname.length; header.mapname[i++] = (char) dis.readByte());
        for (int i = 0; i < header.gamedirectory.length; header.gamedirectory[i++] = (char) dis.readByte());
        header.playback_time = dis.readFloat();
        header.playback_ticks = dis.readInt();
        header.playback_frames = dis.readInt();
        header.signonlength = dis.readInt();    
        return header;
    }

    public void println(){
        PrintStream p = System.out;
        p.print("Filestamp - ");
            for (int i = 0; i < 8; p.print(demofilestamp[i++]));
            p.println();
        p.println("Demo protocol - " + Integer.toUnsignedString( demoprotocol ));
        p.println("Network protocol - " + networkprotocol);
        p.print("Server name - ");
            for (int i = 0; i < servername.length; p.print(servername[i++]));
            p.println();
        p.print("Client name - ");
            for (int i = 0; i < clientname.length; p.print(clientname[i++]));
            p.println();
        p.print("Map name - ");
            for (int i = 0; i < mapname.length; p.print(mapname[i++]));
            p.println();
        p.print("Game directory - ");
            for (int i = 0; i < gamedirectory.length; p.print(gamedirectory[i++]));
            p.println();
        p.println("Play back time - " + playback_time);
        p.println("Play back ticks - " + playback_ticks);
        p.println("Play back frames - " + playback_frames);
        p.println("Sign on length - " + signonlength);

    }

}

Reading a random .dem file's header and printing it results in

Filestamp - HL2DEMO
Demo protocol - 67108864
Network protocol - -684457984
Server name - eBot :: ENVYUS vs E-Frag.net
Client name - GOTV Demo
Map name - de_cache
Game directory - csgo
Play back time - 1.9518368E-38
Play back ticks - 1084033024
Play back frames - 345769984
Sign on length - -544012032

which is wrong for all numbers (e.g. demoprotocol must be 4). What am I doing wrong?

Upvotes: 1

Views: 199

Answers (1)

Sven Schoenung
Sven Schoenung

Reputation: 30564

I downloaded a random .dem file from the web. Using your code I get the following output:

Filestamp - HL2DEMO
Demo protocol - 67108864
Network protocol - -801898496
Server name - eBot :: mousesports vs E-Frag.net
Client name - GOTV Demo
Map name - de_cache
Game directory - csgo
Play back time - 6.5734844E19
Play back ticks - 595788800
Play back frames - -1451097088
Sign on length - -1433729280

Notice how I get the same number for Demo protocol as you do.

So I opened the file in a hex editor. This is what the first 12 bytes look like:

48 4C 32 44 45 4D 4F 00 04 00 00 00

The first 8 bytes (48 4C 32 44 45 4D 4F 00) form the string HL2DEMO (plus the terminating null byte \0). But notice the next 4 bytes: 04 00 00 00. That's the integer value 4, but in Little Endian. Java's DataInputStream reads int as Big Endian.

Using Guava's LittleEndianDataInputStream instead of Java's DataInputStream I get the following output:

Filestamp - HL2DEMO
Demo protocol - 4
Network protocol - 13520
Server name - eBot :: mousesports vs E-Frag.net
Client name - GOTV Demo
Map name - de_cache
Game directory - csgo
Play back time - 2310.2734
Play back ticks - 295715
Play back frames - 295593
Sign on length - 494506

Upvotes: 2

Related Questions