![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Expert Programmer
|
Storing Data
How do I store data to a text file in C++?
__________________
|
|
|
|
|
|
#2 |
|
Professional Programmer
Join Date: May 2005
Location: Woo - Boot Sector!
Posts: 294
Rep Power: 4
![]() |
try writing to it, then reading from it?
__________________
www.heldtogether.co.uk |
|
|
|
|
|
#3 |
|
Expert Programmer
|
What I wanted to do was take an input from the program and save it to a text file
__________________
|
|
|
|
|
|
#4 |
|
Battle Programmer
Join Date: Feb 2006
Location: Bellevue, WA, USA
Posts: 773
Rep Power: 3
![]() |
look up how to use fstreams and operator overloading. You'll probably want to be overloading ostream& operator<< (ostream&, YourType&) and istream& operator>> (istream&, YourType&).
|
|
|
|
|
|
#5 | ||
|
Resident Grouch
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jun 2005
Posts: 6,453
Rep Power: 10
![]() |
This is material to be put into a "Common Questions" thing I'm working on. It's rough, yet.
HOW TO OPEN AND USE A FILE Methods for opening files for reading and writing might be classified as C++, C stream, and C low-level methods. There are numerous variations, particularly with C++ streams; this post can in no way be considered exhaustive. CHECK YOUR DOCUMENTATION. A NOTE ABOUT MODE Unix/Linux have only one mode for file operations: binary. Windows has a text mode which is, unfortunately, the default. In text mode, content beyond what you supply is written to the file; it is stripped when you read the file. This makes the use of random access (seek, tell, etc.), problematic. Even worse, a 'soft' EOF, a special character, is written. This indicator is NOT MOVED if you do an append, so appended data is not reachable unless you reset the EOF indication. Consequently, I recommend always using binary mode. With 'fopen,' you can specify a read or write or other mode as "rb", "wb", etc. Unix/Linux will accept and ignore the 'b', so you can use it portably. You can also set the default mode in Windows with the global variable, _fmode. C++ USING FSTREAM VC++ 6.0, Windows XP Include iostream, fstream, and string for the following examples. FSTREAM OPENING FOR WRITE // Example variables
string sFileName = "test.txt";
string sContents = "File data\n";
string sToken;
char lineBuffer [256];
int nCount = 0;
// Construct an fstream object and attempt to open
// for output
fstream ooFile;
ooFile.open (sFileName.c_str (), ios::binary | ios::out);
// Test for success
if (!ooFile.is_open ()) return badHappenstance ("Couldn't open file for writing");
// Write example
ooFile << sContents;
// Test the write for success
if (!ooFile.good ()) return badHappenstance ("Write failed");
// Close the file. Note that the file will be closed automatically when
// the object is destroyed (goes out of scope).
ooFile.close (); // Open it for input
ooFile.open (sFileName.c_str (), ios::binary | ios::in);
if (!ooFile.is_open ()) return badHappenstance ("Couldn't open file for reading");
// Read tokens until end of file or error
while (ooFile.good ())
{
ooFile >> sToken;
cout << "Token " << ++nCount << ": ";
if (sToken.size ()) cout << sToken; else cout << "(null token)";
cout << endl;
}
// Check some status for grins
if (ooFile.eof ()) cout << "Reached EOF" << endl;
else if (ooFile.fail ()) return badHappenstance ("Read failed for some reason");
// Alternatively, read entire line
ooFile.getline (lineBuffer, sizeof (lineBuffer));
// Always the status
if (!(ooFile.good () || ooFile.eof ()))
return badHappenstance ("Failure reading line");
cout << "This is the line: " << lineBuffer << endl; // Position to beginning after clearing EOF or fail bits
ooFile.clear ();
ooFile.seekg (0, ios::beg);
if (!ooFile.good ()) return badHappenstance ("Seek failed");
ooFile.close ();[quote] Token 1: File Token 2: data Token 3: (null token) Reached EOF This is the line: File data [quote] C USING FOPEN VC++ 6.0, Windows XP Include stdio.h for this method. OPENING FOR WRITE // Example variables
FILE *ooFile;
char sFileName [] = "test.txt";
char sContents [] = "File data\n";
char sToken [32];
char lineBuffer [256];
int nCount = 0;
int status;
// Attempt to open file for output
ooFile = fopen (sFileName, "wb");
// Test for success
if (!ooFile) return badHappenstance ("Couldn't open file for writing");
// Write the contents
status = fputs (sContents, ooFile);
// Test for success
if (status == EOF) return badHappenstance ("Write failed");
// Close the file
fclose (ooFile); ooFile = fopen (sFileName, "rb");
if (!ooFile) return badHappenstance ("Couldn't open file for reading");
// Read tokens until end of file or error -- one method: fscanf
// fscanf consumes whitespace, unlike some C++ methods
// so there won't be a null token at the end.
while (1)
{
if (fscanf (ooFile, "%s", sToken) != 1)
{
if (feof (ooFile))
{
printf ("Reached EOF\n");
break;
}
else return badHappenstance ("Failed to read token");
}
printf ("Token %d: %s\n", ++nCount, sToken);
}
// REPOSITIONING EXAMPLE
rewind (ooFile);
// Read a line all in one swell foop
// We'll either fill the buffer or have a newline
// at the end of the buffer, or both. If you don't
// want the newline:
//
// index = strlen (lineBuffer) - 1;
// if (lineBuffer [index] == '\n')
// lineBuffer [index] = '\0';"
//
if (fgets (lineBuffer, sizeof (lineBuffer), ooFile) == NULL)
// Always the status; EOF is okay, error is not
if (ferror (ooFile)) return badHappenstance ("Failed to read line");
printf ("This is the line: %s", lineBuffer);
fclose (ooFile);Quote:
As far as I'm concerned, low level file operations are only good for reading large amounts of binary data, and are not necessary for that. One is far better off using the higher level functions. VC++ 6.0, Windows XP Include stdio.h, io.h, fcntl.h, sys\stat.h, ctype.h, and string.h for the following example. OPENING FOR READ/WRITE typedef int fileHandle;
extern int errno;
// Example variables
fileHandle ooFile;
char sFileName [] = "test.txt";
char sContents [] = "File data\n";
char sToken [32];
char sTrash [32];
char lineBuffer [256];
int nChars, nTokens;
int status;
// Attempt to open file for input/output
ooFile = _open ("test.txt", _O_CREAT | _O_RDWR | _O_TRUNC | _O_BINARY, _S_IWRITE);
// Test for success
if (ooFile == EOF) return badHappenstance (strerror (errno)); // Write the contents
status = _write (ooFile, sContents, strlen (sContents));
// Test for success
if (status == EOF) return badHappenstance ("Write failed"); // Return to the beginning for input
if (_lseek (ooFile, 0, SEEK_SET) == -1L)
return badHappenstance ("Seek to beginning failed");
// Read tokens until end of file or error
nTokens = 0;
while (1)
{
// Skip any whitespace
while (status = _read (ooFile, sTrash, 1) == 1)
if (!isspace (sTrash [0])) break;
// Check for EOF or failure
if (status < 0) return badHappenstance ("Failure to read data");
else if (status == 0) break;
sToken [0] = sTrash [0];
for (nChars = 1; nChars < sizeof (sToken) - 1; nChars++)
{
status = _read (ooFile, &sToken [nChars], 1);
// Check for EOF or failure
if (status < 0) return badHappenstance ("Failure in reading data");
else if ((status == 0) || (isspace (sToken [nChars])))
{
sToken [nChars] = '\0';
break;
}
}
// The token could be too long...
if (nChars >= sizeof (sToken) - 1)
{
sTrash [0] = ' ';
// Skip any remaining non-whitespace characters
while (status = _read (ooFile, sTrash, 1) == 1)
if (!isspace (sTrash [0])) break;
// Check for EOF or failure
if (status < 0) return badHappenstance ("Failure in reading data");
else if (status == 0) break;
}
// Or we could have completed the token
if (strlen (sToken) > 0) printf ("Token %d: %s\n", ++nTokens, sToken);
}
printf ("End of file\n");
// Reposition to beginning
if (_lseek (ooFile, 0, SEEK_SET) == -1L)
return badHappenstance ("Seek to beginning failed");
// Read one buffer's worth
status = _read (ooFile, lineBuffer, sizeof (lineBuffer) - 1);
if (status > 0)
lineBuffer [status] = '\0';
printf ("This is the line: %s", lineBuffer);
_close (ooFile);
return 0;
}Quote:
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code. Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers |
||
|
|
|
|
|
#6 | |
|
Hobbyist Programmer
Join Date: Jan 2006
Location: Menidi, Athens, Greece
Posts: 243
Rep Power: 4
![]() |
Dawei, I want to ask you something about this:
Quote:
And now my question. I am concerned about the problems you mentioned with the plain text file operation mode. It seems I am using that, at the moment, and I hadn't noticed the problems you mentioned, because I wasn't able to test them extensively, nor have I needed to access randomly a file. Can you tell me what is stripped exactly?
__________________
Project::Soulstorm (personal homepage) |
|
|
|
|
|
|
#7 |
|
Resident Grouch
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jun 2005
Posts: 6,453
Rep Power: 10
![]() |
Many people have this "feeling" that text and binary mode files use different encoding. It isn't so; it's the same. An ASCII 'A" will be written as 0x41 in both modes. The fact that it's also the value 65 is immaterial. You just have to know what your file contains. It's why files have extensions and magic numbers and all that hooey.
You may note when you're building strings that you use a newline as an ending. Where, then, is the dreaded Windows line ending of \r\n? It's built in text mode (not that you couldn't build it yourself). On output (in text mode), Windows prepends \r to each \n. On input, it's stripped. The other operation is to add the soft EOF, 0x1A, ctrl-Z. That's it. Obviously, if you read a binary file (by which I mean one with all sorts of byte-values), you're going to see EOF a lot. This is a common problem for novices. "I only read a little of my data file, then it just stops!!!" Then there is the problem of appending to a file, as mentioned above. One has to choose the proper append mode. One would NEVER want to use text mode with files containing non-textual data. The questions is: should one use binary mode with textual data? As I said, it doesn't affect the text, other than line endings and the EOF mark. The addition of material by the function means that you can't rely on the file having the length you expect. That's why seeks and tells are problematic. I have no earthly idea why you are having a problem with OS X, because I'm not familiar with it. It has nothing to do with text/binary mode differences as they apply to Windows machines. The difference you will see because of that will be double-spaced lines or files with no line breaks, depending on which way the file was written and whether or not the reproducing program is relying on the \r\n. There are no differences in encoding methods which relate to the file mode. Encoding variations because of locale, unicode, ASCII, things like that, are another picture which has nada to do with the file mode. Any documentation regarding file operations that is provided by Microsoft will tell you in detail about these things. Some here and some there, maybe, but you will find it all with little trouble. The PHP manual discusses it, also. You may independently verify this information for yourself. NOTE TO MOD: The [ quote ] in the fourth box down, my original post, should be [ /quote ]. I garfled it up.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code. Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers Last edited by DaWei; Jun 24th, 2006 at 7:33 AM. |
|
|
|
|
|
#8 |
|
Programmer
|
Mac has traditionally used \r instead of \n - so maybe OSX has the distinction.
DaWei: you should mention somwhere to use namespace std for that code. apart from that, _open etc are not standard I believe - what's wrong with stdio.h functions like fopen ? |
|
|
|
|
|
#9 | |
|
Resident Grouch
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jun 2005
Posts: 6,453
Rep Power: 10
![]() |
Perhaps you should read the post as well as study your C.
What's wrong with fopen? Did you not read this part? // Attempt to open file for output
ooFile = fopen (sFileName, "wb");
// Test for success
if (!ooFile) return badHappenstance ("Couldn't open file for writing");
...blah blah blahQuote:
If you find errors in the presentation, please tell me. If you have differing ideas about presenting information, please make a contribution.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code. Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers |
|
|
|
|
|
|
#10 | ||
|
Hobbyist Programmer
Join Date: Jan 2006
Location: Menidi, Athens, Greece
Posts: 243
Rep Power: 4
![]() |
Quote:
I have no problems with OS X input/output whatsoever. The only reason that I asked you these things was to make certain that I have understood everything right, and that I will not encounter any problem in the future, that's all. Quote:
__________________
Project::Soulstorm (personal homepage) |
||
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|