Jump to content
  • Advertisement
Sign in to follow this  
synth_cat

which file-load method is best?

This topic is 4435 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

The finished version of my game (written in Visual C++ 2005 Express) needs to be able to handle files. It needs to be able to load my own world files float by float or int by int. It also needs to be able to save player-stats files int by int or float by float. I would like to be able to write to .txt files in order to output debug info to track problems with my program. Finally, I want my world editor to be able to load X files (which I'm hoping won't be as difficult as it seems.) I currently use f_open_s(), fwrite(), and fread() for all my file work (I have only so far added the functionality to create and load my world files - I have done nothing on text files or X files so far.) But I've seen people use many other ways to handle files. I've seen stuff done with the std class (which has always intimidated me for some reason) and even something like cin.Openfile(). So which way is the right way to do this? What method do you guys use? Are any of the available methods unsafe? Another question: in the context of writing and reading files, I've heard people say that there are two types of files: "text" and "binary." What is this supposed to mean? All files are binary, obviously. Will I need to worry about the difference between these two file types for the tasks I plan on doing? Thanks for your help!

Share this post


Link to post
Share on other sites
Advertisement
The fastest method that I know of is to allocate a buffer the size of the entire file, then read it in through binary mode in a single call.

This leaves it all to the runtime / OS, which I would assume knows best how to do these things.

As a text file, one can do things such as read them in line-by-line, or even open them up in a text editor.

To store a float in text format generally involves storing a byte sequence which represents the string of ASCII characters used to display it in human-readable form. ie: 1.000000

To store a float in binary format involves storing a byte sequence which represents the CPU format of this type of variable. sizeof(float) will tell you how many bytes it requires to store the variable. If you try to open the binary file in a text editor, the data will end up looking nothing like 1.000000 at all.

In C++, one uses the ifstream and ofstream objects using the ios_base::binary flag to open in binary mode. The default is text mode.

The .read and .write members are used to transfer data from disk to memory (in the form of an array), and back again.

In C++ the stream operators << and >> can be used in conjunction with the stringstream objects in order to easily process text files that contain all forms of data in their ASCII representation.

Share this post


Link to post
Share on other sites
But which method should I use? Is f_open_s OK? Will fwrite() work for writing to text files, or should I just use std to do that? If so, can someone please show me implementation?

Thanks!

Share this post


Link to post
Share on other sites
What is f_open_s? I searched google for: f_open_s c++. I didn't get anything. Then, searching for only: f_open_s, I got a bunch of things, but all were about Lisp.

You prolly confused with fopen from C.

BTW, to write text to files, you can use the C stuff: fopen, fprintf and fscanf. Many people dislike it, tho. fwrite and fread reads file on binary more, so they will read groups of bytes, not text or numbers.

Share this post


Link to post
Share on other sites
fopen_s is what you need. fopen and fopen_s do the same thing. The FILE * returned can be used in the same way and must be closed the same way with fclose. The only difference is that fopen_s has the _s (deemed secure in the new CRTs). For fopen_s, it returns an error code instead of the FILE*, and it takes in a FILE ** so that it can fill your pointer with a valid FILE *

Binary i/o is a little faster than text, but not much. fwrite probably shouldn't be used with text output (I say "probably" because the only difference is the newline translation, you could just avoid that character, but its a bit of a hassle). For text output, use fprintf. For text input, use fscanf. At least those are my favorites.

Share this post


Link to post
Share on other sites
Quote:
Original post by synth_cat
I currently use f_open_s(), fwrite(), and fread() for all my file work (I have only so far added the functionality to create and load my world files - I have done nothing on text files or X files so far.)


Please don't; the new methods are much nicer.

Quote:
But I've seen people use many other ways to handle files. I've seen stuff done with the std class (which has always intimidated me for some reason) and even something like cin.Openfile().


std is not a class; it's a namespace. It is the namespace into which all stuff from the standard library - classes, free functions, and global object instances - are placed.

The <iostream> header (NOT <iostream.h>) provides a definition for std::iostream (i.e. the class iostream, in the std namespace). It also provides global instances std::cin and std::cout of this class (actually, they are of derived classes std::istream and std::ostream respectively). The <fstream> header defines a class std::fstream, which is another class derived from std::iostream (and which in turn also has derived classes std::ifstream and std::ofstream).

To read from a file, you typically create an instance of std::ifstream, and then use its member functions. You can use one of the std::ifstream constructors to specify a file name right away: e.g. std::ifstream my_world("world.txt");.

Quote:
Another question: in the context of writing and reading files, I've heard people say that there are two types of files: "text" and "binary." What is this supposed to mean? All files are binary, obviously. Will I need to worry about the difference between these two file types for the tasks I plan on doing?


There are two concepts here, which are commonly confused. The first is the file *formatting*, and the second is the file stream *mode*. Usually, you want to open a file that you know is "text formatted" with a text stream, and binary with binary.

Text-formatted data is normally written and read with the stream "insertion" and "extraction" operators. Those are the >> and <<, same as you're presumably used to using with cout and cin. (Now you understand what's going on with those statements: actually you are calling member functions of a stream object that represents the console.) Those operators do input or output with the right-hand-side as a side effect, and *evaluate to* a reference to the left hand side. (That's why you can "chain" the operator: if you do cout << foo << bar;, then what happens is cout << foo is first evaluated, outputting foo and evaluating to cout, and then cout << bar is similarly evaluated, because the left-hand side of that operator is simply the cout yielded by the first evaluation.) You *can* handle text-formatted data with binary-formatted-data operations, but you're making things needlessly difficult for yourself.

Binary-formatted data is normally written and read with stream member functions like .read() and .write(). There are a lot of them (there are more text-formatted-data operations as well that you should read up on), but suffice to say briefly that they try to treat your file as a raw sequence of bytes; if you expect an integer value in the file, you would expect not a text representation of that number (i.e. something you could read on screen as a base 10 number if you opened the file with a text editor), but a sequence of bytes corresponding to the byte values that would be used in memory to represent that number.

A stream opened in text mode performs line-feed translation, so that your platform's normal new line encoding (which might be "\n", "\r" or "\r\n") is translated to a nice consistent "\n". It will also interpret some specific character value (on Windows this is ASCII 26 - i.e. control-Z; on Unix it's ASCII 4 - i.e. control-D) as "end of file", and refuse to read anything that might be in the file beyond that point. These are both generally considered desirable properties for a file with text-formatted data, but highly undesirable properties for a file with binary-formatted data.




You really, really, really should read this documentation (including as many subpages as you can tolerate) and this and this FAQ.

Share this post


Link to post
Share on other sites
Quote:

The fastest method that I know of is to allocate a buffer the size of the entire file, then read it in through binary mode in a single call.
This leaves it all to the runtime / OS, which I would assume knows best how to do these things.

If it is speed you want, check out a little paper on speeding up I/O.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!