C++ fstream.read() question... - Programmers Heaven

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

C++ fstream.read() question...

SephirothSephiroth Fayetteville, NC, USAPosts: 1,035Member
I'm trying to go more to the C++ side of things and break away from plain old C and part of that is using fstream for file access instead of fread/fwrite. I know how to open a file for reading and/or writing, but when it comes to the actual reading and writing of binary files I am still not sure that I am coding it properly. Below is a chunk of code designed to read in a section of binary data from a GTA:SA save game. The code compiles without warning or error, but I just feel uneasy about it since everything has to be type-cast to char* just to read in. Can somebody offer me some advice on reading and writing data with fstream? I mean binary files, not text-mode.
[code]
//Read the car object data from the current stream location
pFile->read((char*)this->pPosition, 12); //float[3]
pFile->seekg(ios::cur, 4);
pFile->read((char*)&(this->ucFlags), 1); //unsigned char
pFile->seekg(ios::cur, 1);
pFile->read((char*)&(this->sModelID), 2); //short
pFile->read((char*)this->pMods, 30); //short[15]
pFile->read((char*)this->pColors[0], 1); //unsigned char[4]
pFile->read((char*)this->pColors[1], 1); //unsigned char[4]
pFile->read((char*)this->pColors[2], 1); //unsigned char[4]
pFile->read((char*)this->pColors[3], 1); //unsigned char[4]
pFile->read((char*)&(this->ucRadioStation), 1); //unsigned char
pFile->read((char*)this->pVariation, 2); unsigned char[2]
pFile->read((char*)&(this->ucBombType), 1); //unsigned char
pFile->read((char*)&(this->ucPaintJob), 1); //unsigned char
pFile->read((char*)&(this->ucNitrous), 1); //unsigned char
pFile->read((char*)this->pRotation, 3); //unsigned char[3]
pFile->read((char*)&(this->ucAlign), 1); //unsigned char
[/code]
I am specifically not sure whether or not I coded the color section properly since I am specifying a specific point in the color array. Thanks for any help you can offer.

-[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

Comments

  • richfellrichfell Posts: 17Member
    Sephiroth, one thing about pColors. I am assuming from your comment that it is of type "unsigned char[4]"? If that is correct then you would need:

    [code]
    ...
    pFile->read((char*)&this->pColor[0], 1);
    pFile->read((char*)&this->pColor[1], 1);
    pFile->read((char*)&this->pColor[2], 1);
    pFile->read((char*)&this->pColor[3], 1);
    ...
    [/code]

    I think that you could code the reading of those four values like this as well:

    [code]
    ...
    pFile->read((char*)this->pColor, 4);
    ...
    [/code]

    Perhaps another thing to consider adding is some error checking after the read calls using fstream::fail.
  • SephirothSephiroth Fayetteville, NC, USAPosts: 1,035Member
    You know, I can read it as a pointer to the array and reading in four bytes. I did that up top with the float array, so I don't know what I was thinking when I coded the colors section. It was late last night, so I must have been shutting my brain down. Thanks for pointing it out though.

    What about the read calls? I am specifying a pointer to a char, but am reading in all kinds of stuff. Is that OK?

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]
  • richfellrichfell Posts: 17Member
    That is OK, essentially all that does is give the starting memory address that read is supposed to use.

    However, I'll make a point, forgive me if you know this already:

    The issue with reading multi-byte values, like float, short or long for example, from a binary file or a binary data stream is [link=http://en.wikipedia.org/wiki/Endianness]endianness[/link]. So unless the file specification states a given endianness for its multi-byte values you may not read the correct values in the case where the file was written under one endian architecture and read under the other endian architecture.

    There is no issue when reading 1 byte values, or an array of 1 byte values.
  • SephirothSephiroth Fayetteville, NC, USAPosts: 1,035Member
    I've actually never run into a problem with endianness. I am writing a program that will edit a GTA:SA save and allow the user to modify, add, or remove vehicles from his or her garages in the game. GTA:SA runs on the PS2, XBox, and PC, but I am using my PC version for this project. Assuming a person could get a PS2 or XBox save onto a Windows machine, that may be the only place I could see a problem with endianness. That said, is there a way to detect this, or is it something that must be known beforehand?

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]
  • richfellrichfell Posts: 17Member
    In general there is no way to detect the endianness unless there is a (1 byte) field purposefully stored in the file to indicate the byte order. I did a quick google for the [link=http://www.gtamodding.com/index.php?title=GTA_SA_Saves#Data_Blocks]GTA:SA save game file format[/link] and I don't see that they built that into the structure. I'm not sure if any Windows versions run on big-endian HW but if you give you program to a friend you may want to make sure they are running on a compatible architecture :)

  • LundinLundin Posts: 3,711Member
    This has nothing to do with the OS, but the processor.

    PC and Xbox have Intel CPUs = little endian. Playstation seems to use some custom-made CPU, I don't know whether it is big/little endian.
  • richfellrichfell Posts: 17Member
    Yes, it's the processor. Please read my post more carefully...

    :I'm not sure if any Windows versions run on big-endian [b]HW[/b]...

    Apparrently the XBox 360 is big-endian, interesting to hear that the original was little-endian.
  • SephirothSephiroth Fayetteville, NC, USAPosts: 1,035Member
    Yes, that is huge reason that the 360 is an epic failure. It can't play 90% of the games that were for the XBox. All of the Playstations are little-endian as far as I know, and they all play old games. You can even play PS1 games on a PS3!

    Consoles aside, I myself have already deciphered much of the save format myself and upon looking at that link, I was right in my discoveries. I have a few things that the link doesn't, however. I'm building the UI around the class now, since my fstream question was answered.

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]
Sign In or Register to comment.