Size of a file in C?

Discussion in 'Game Development (Technical)' started by lapskaus, Jul 12, 2006.

  1. lapskaus

    Original Member

    Joined:
    Jun 16, 2006
    Messages:
    51
    Likes Received:
    0
    Hello everybody!

    I'm currently trying to write my own little archive file format to avoid having hundreds of loose .tgas lying around in my game dir. Now, i'm having trouble figuring out how to get the size of a file opened using fopen(). My code looks something like this:

    Code:
    FILE file;
    loop{
        // get filename from script
        file = fopen(filename, "rt");
        // ???
        fclose(file);
    }
    I need something like what you would get from calling sizeof(something), but sizeof(file) obviously doesn't work, it always returns 4. Does anyone have any ideas?
     
  2. Slayerizer

    Original Member

    Joined:
    Dec 13, 2004
    Messages:
    103
    Likes Received:
    0
    Gets a stream's file-position indicator

    Code:
    int fgetpos( 
       FILE *stream,
       fpos_t *pos 
    );
    
    declared in stdio.h
     
  3. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    Code:
    nPos = fTell(pFile);
    fseek(pFile, 0, SEEK_END);
    nSize = ftell(pFile);
    fseek(pFile, nPos, SEEK_SET);
    This is a very basic question. Are you sure you want to implement your own archive format?
     
  4. lapskaus

    Original Member

    Joined:
    Jun 16, 2006
    Messages:
    51
    Likes Received:
    0
    Hey, thanks :D

    Still confused though. Never worked with fpos_t before.. i typed in:

    fpos_t pos;
    int size = fgetpos(file, &pos);

    but size is always 0?

    Nevermind (edit)
    ggambett's code worked. Thanks for the speedy reply guys!
     
  5. Slayerizer

    Original Member

    Joined:
    Dec 13, 2004
    Messages:
    103
    Likes Received:
    0
    well you confused SIZE with the return code, fgetpos return 0 on success.
    To be honest, I gave an incomplete answer since fgetpos is the same as ftell.
    It gives you the current position in the file. To know the file's length, you need to go to the end of the file prior to call fgetpos or ftell.

    fpos_t *pos;

    fseek(File, 0, SEEK_END); //move to end of file
    if (fgetpos(file, &pos)==0) //get position
    {
    //the position = length of file
    }
     
  6. jetro

    Original Member

    Joined:
    Jan 21, 2005
    Messages:
    130
    Likes Received:
    0
    If you're looking into using an archive to store game assets (most commonly called "packfiles" in context of games I think), there's some good and easy to use existing ones available. I recommend you take a look at e.g. Sol's CFL3 (look for cfl3r3.zip, check out also the ramfile.zip) or the PhysicsFS.
     
  7. Gilzu

    Moderator Original Member

    Joined:
    Jul 27, 2004
    Messages:
    368
    Likes Received:
    8
    and a nice tutorial for those who are using SDL (the undocumented SDL_RWops will save you the code needed to convert raw image code to SDL_surface): http://www.kekkai.org/roger/sdl/rwops/rwops.html
     
  8. James C. Smith

    Moderator Original Member

    Joined:
    Aug 21, 2004
    Messages:
    1,768
    Likes Received:
    0
    Basally you want to seek to the end of the file and then ask for the current position in the file to get the file's size.

    Here is the code I use in my file wrapper class

    Code:
    ulong CFileBuf::GetLength() const
    {
    	if(m_pFile)
    	{
    		long Mark;
    		long Length;
    
    		Mark = ftell(m_pFile);
    		fseek(m_pFile, 0, SEEK_END );
    		Length = ftell(m_pFile);
    		fseek(m_pFile, Mark, SEEK_SET );
    		return Length;
    	}
    
    	return 0;
    }
    
    The Mark stuff if only needed if you wan't to preserve the curront posion in the file. If you don't mind losing the position, you can just fseek to the end and then use ftell to get the position. For example

    Code:
     FILE* pFile = fopen("Afile.txt", "rb");
     fseek(m_pFile, 0, SEEK_END );
     Length = ftell(m_pFile);
    
    Make sure you open the file in binary mode (the "B" in the fopen string). Otherwise the ftell will give unpredictable results due to the way text mode deals with line breaks.
     
  9. James C. Smith

    Moderator Original Member

    Joined:
    Aug 21, 2004
    Messages:
    1,768
    Likes Received:
    0
    FYI: My pack file format of choice is non-compressed .ZIP files. There are not very difficult to parse yourself and then you don't need to make any custom tools for creating them. Beast of all, the available tools are very robust with the ability to view and edit the contents of the files. All the games I have every worked on have all used (disguised) zip files to store all the games assets. Most of them (such as Ricochet and Big Kahuna) use a file called data.dat which is actually a zip archive.
     
  10. sparkyboy

    Original Member

    Joined:
    Mar 3, 2005
    Messages:
    346
    Likes Received:
    0
    On the subject of creating your own archive file, and/or protecting your assets from prying eyes, when I was seriously bitten by the programming bug years ago, what I did was to write a small program that would load in individual .wav and .pcx files, replace the 'identifier'(header) byte or bytes then spit the files back out.
    Then from within my game I would search for my 'marker' byte/s, then after that start to load in the information from the .wav or .pcx file until the end of the file was reached.
    That way, I still had individual files in the directory, but no original headers to prevent 'normal' programs from reading them.

    I didn't get around to joining the files together into a single file though, though I would imagine that it would simply be a case of loading one file at a time into an array, writing your own 'identifiers' for the start and maybe end of each file then appending each subsequent file to the outgoing archive. On reloading into your game, you would simply search for the 'beginning' identifier, then load the necessary information until you reach the start of the next file, and continue on until the end of the archive.

    I know there are many ways to do this, but if I had done this, I would have had 1 sound and 1 graphic archive.


    I have no real code ( been a long long time since I did any 'C' programming :eek: ), so I apologise if I'm way off track here.


    All the best


    Mark.
     
  11. milo

    Original Member

    Joined:
    Sep 10, 2004
    Messages:
    86
    Likes Received:
    0
    If you do decide to create your own compressed archive format, at least consider using an open-source compression library such as zlib.

    http://www.zlib.net/

    --milo
     
  12. Arthur

    Original Member

    Joined:
    May 10, 2005
    Messages:
    52
    Likes Received:
    0
    In general, are there really compelling reasons to hide a game's assets from 'prying eyes'?

    If I am not mistaken, Popcap just installs the assets 'loose', and they seem to be doing ok.

    Won't anyone who really wants to get at your assets find a way, anyway?
     
  13. Fabio

    Original Member

    Joined:
    Sep 30, 2005
    Messages:
    499
    Likes Received:
    0
    I personally think that lotsa files look less polished, etc..

    At the very least a directory "Data" should be created and everything put in, in my opinion at least.

    Finding an EXE among hundreds of data files, DLL's and possibly other EXEs is really a pain IMHO. Providing a link in the Start Menu is not a "total solution".
     
  14. mahlzeit

    Original Member

    Joined:
    Sep 26, 2004
    Messages:
    852
    Likes Received:
    0
    License agreements for sound files, etc, that you licensed from third parties. Sometimes they require this.
     
  15. lapskaus

    Original Member

    Joined:
    Jun 16, 2006
    Messages:
    51
    Likes Received:
    0
    Well, i just loaded a sprite into my game from my very own archive :D Thanks for all the help! It crashes when i try to import files that are larger than 2mb, when i try to create an array of char[filesize]. Guess the size of an array has it's limits.. oh well, i won't need to archive bigger files anyway, so i can't be arsed to do a workaround ;)

    I don't have any real reason for doing it really. I just like to keep a small tidy directory. My game's probably going to have at least 200-300 small images floating around. Replacing all those with one file seems like a good idea. And coding it was a fun little side-project!
     
  16. Fabio

    Original Member

    Joined:
    Sep 30, 2005
    Messages:
    499
    Likes Received:
    0
    Linker options: /STACK

    Default is 1MB.
     
  17. lapskaus

    Original Member

    Joined:
    Jun 16, 2006
    Messages:
    51
    Likes Received:
    0
  18. Emmanuel

    Moderator Original Member

    Joined:
    Nov 23, 2004
    Messages:
    859
    Likes Received:
    0
    You probably shouldn't allocate a 2 MB object on the stack; use the heap instead:

    Code:
       unsigned char *lpBuffer = new unsigned char[nBufferSize];
    
       ...
    
       delete [] lpBuffer;
    
    or

    Code:
       unsigned char *lpBuffer = (unsigned char *) malloc (nBufferSize);
    
       ...
      
       free (lpBuffer);
    
    (Insert Cas telling us about garbage collection here ;))

    Best regards,
    Emmanuel
     
  19. Larry Hastings

    Original Member

    Joined:
    Jul 27, 2004
    Messages:
    213
    Likes Received:
    0
    Guys, the function you're looking for is fstat(). It simply tells you the size of an open file handle. The one fly in the ointment: it doesn't take a FILE *, it takes an int "handle" (like what open() gives you). To convert a FILE * to the appropriate int, call fileno().

    On Windows, just to be irritating, all these functions have an underscore in front of them: _fstat(), _fileno(), and even _open(). Then again, if you're on Windows, you should be using native handles--as with CreateFile() and GetFileSize().
     

Share This Page

  • About Indie Gamer

    When the original Dexterity Forums closed in 2004, Indie Gamer was born and a diverse community has grown out of a passion for creating great games. Here you will find over 10 years of in-depth discussion on game design, the business of game development, and marketing/sales. Indie Gamer also provides a friendly place to meet up with other Developers, Artists, Composers and Writers.
  • Buy us a beer!

    Indie Gamer is delicately held together by a single poor bastard who thankfully gets help from various community volunteers. If you frequent this site or have found value in something you've learned here, help keep the site running by donating a few dollars (for beer of course)!

    Sure, I'll Buy You a Beer