Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Reading and Writing to Binary Files

Reply
Thread Tools

Reading and Writing to Binary Files

 
 
Daniel Moree
Guest
Posts: n/a
 
      11-23-2004
I'm working on a program that must first establish if the file exists in the
program directory then it must open if for reading, read each line and set
the variables then the program goes on about it's buisness.

My problem is all the resources I have found aren't very clear on these
things. All of them open the file then check to see if the stream is open.
Well, the problem with using file.open("filename.dat", ios::in |
ios::binary) is that if the file doesn't exists, it creates it
automatically. I need to see if the file exists, if it doesn't show an error
message, then if the file does exists, open if, read from it, then set the
global program variables. Below is my code so far to try to get this work.

I've marked where I needed help with // Need help here and many question
marks
Hopefully you guys will get a good view of what i'm doing, just a basic
console app in MSVC++ that pulls information in a binary file then if that
is successful allow you to set the variables to something else. Then run the
program again and view the information then set it to something different.

===== MAIN.CPP =====
#include <iostream.h>
#include <fstream.h>
#include <iomanip.h>

// variables
int Box_X;
int Box_Y;
int Box_Z;
float input_X;
float input_Y;
float input_Z;
char* filename = {"main.dat"};

// Functions
bool pullconfig();
bool setconfig();

// main function
int main(){
cout << "Pulling configuration information...\n";
if(pullconfig() == false){
cout << "\nError opening \"main.dat\" file: Does Not Exist!\n";
return 0;
}
cout << "Configuration pulled successfully!\n";
cout << "\nBox_X = " << Box_X << "; Box_Y = " << Box_Y << "; Box_Z = "
<< Box_Z << "\n";
cout << "Set Box_X to: ";
cin >> input_X;
cout << "Set Box_Y to: ";
cin >> input_Y;
cout << "Set Box_Z to: ";
cin >> input_Z;
if(setconfig() == false){
cout << "\nError setting configuration information!\n";
return 0;
}
cout << "\nNew Configuration Set Successfully!";
return 0;
}

bool pullconfig(){
ifstream fin(filename, ios::in | ios::binary);
if(!fin.is_open()){
return(false);
}

// Need Help here for pulling info and setting it to Box_X, Box_Y, and
Box_Z ????????????????????????????????
return(true);
}

bool setconfig(){
ofstream fout(filename, ios:ut | ios:binary);
if(!fout.is_open()){
return(false);
}
fout << "Box_X = " << input_X << "\n";
fout << "Box_Y = " << input_Y << "\n";
fout << "Box_Z = " << input_Z << "\n";
fout.close();
return(true);
}



 
Reply With Quote
 
 
 
 
Jonathan Mcdougall
Guest
Posts: n/a
 
      11-23-2004
> I'm working on a program that must first establish if the file exists in the
> program directory then it must open if for reading, read each line and set
> the variables then the program goes on about it's buisness.
>
> My problem is all the resources I have found aren't very clear on these
> things. All of them open the file then check to see if the stream is open.
> Well, the problem with using file.open("filename.dat", ios::in |
> ios::binary) is that if the file doesn't exists, it creates it
> automatically.


This is not the standard behavior.

# include <fstream>

int main
{
std::ifstream ifs("myfile");

if ( ! ifs )
{
// file does not exist or some other error
}
}


> I need to see if the file exists, if it doesn't show an error
> message, then if the file does exists, open if, read from it, then set the
> global program variables. Below is my code so far to try to get this work.


If your standard library does that, change it. If you can't use
implementation-defined functions which will probably give you many more
options, such as checking if a file exists.

> ===== MAIN.CPP =====
> #include <iostream.h>
> #include <fstream.h>
> #include <iomanip.h>


Non standard.

# include <iostream>
# include <fstream>
# include <iomanip>

using namespace std;

This could be the source of your problem. I put the using declaration
here to make the code work, but do read about its associated problems.

> // variables
> int Box_X;
> int Box_Y;
> int Box_Z;
> float input_X;
> float input_Y;
> float input_Z;
> char* filename = {"main.dat"};


Global variables are best avoided.

> // Functions
> bool pullconfig();
> bool setconfig();
>
> // main function
> int main(){


<snip>

> }
>
> bool pullconfig(){
> ifstream fin(filename, ios::in | ios::binary);
> if(!fin.is_open()){
> return(false);
> }
>
> // Need Help here for pulling info and setting it to Box_X, Box_Y, and
> Box_Z ????????????????????????????????


I don't know about the file format, but have a look at this.

// file.txt
123
456
789


// main.cpp
# include <iostream>
# include <fstream>
# include <sstream>
# include <string>

int main()
{
std::ifstream ifs("file.txt");
int box_x = 0, box_y = 0, box_z = 0;

if ( ! ifs )
{
std::cout << "There was an error with the file";
return 1;
}

std::string line;
std::istringstream iss;

std::getline(ifs, line);
iss.str(line);
iss >> box_x;

std::getline(ifs, line);
iss.str(line);
iss >> box_y;

std::getline(ifs, line);
iss.str(line);
iss >> box_z;

std::cout << box_x << box_y << box_z;
}

(untested and lots of error checking left out)

Jonathan
 
Reply With Quote
 
 
 
 
Daniel Moree
Guest
Posts: n/a
 
      11-23-2004
Thanks for your help. This is the best response i've gotten yet. I'm using
the C++ Primer Plus Third Edition. I tried using the standard namespace and
i had the same errors so i figured that it wouldn't make a difference
whether I used #include <iostream.h> or #include <iostream> using namespace
std;

I'll try messing with this and see If I can get any of it to work for me.
I'll post back and let you know

Daniel Moree


 
Reply With Quote
 
Jonathan Mcdougall
Guest
Posts: n/a
 
      11-23-2004
> I tried using the standard namespace and
> i had the same errors so i figured that it wouldn't make a difference
> whether I used #include <iostream.h> or #include <iostream> using namespace
> std;


The difference is simple : the former is not standard and the latter is.
The next time you get errors when using standard headers, post it here
and we will be able to help you.

> I'll try messing with this and see If I can get any of it to work for me.
> I'll post back and let you know


Good.


Jonathan
 
Reply With Quote
 
Daniel Moree
Guest
Posts: n/a
 
      11-23-2004
I've messed around with it and checked out my copy of MSDN and can't quit
figure out the error.

this is the file:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

using namespace std;

int main()
{
ifstream fin("main.dat");
int box_x = 0, box_y = 0, box_z = 0;

if(!fin ){
cout << "There was an error with the file\n";
return 1;
} else {
cout << "File found! Printing Contents:\n\n";

string line;
istringstream iss;

getline(fin, line);
iss.str(line);
iss >> box_x;

getline(fin, line);
iss.str(line);
iss >> box_y;

getline(fin, line);
iss.str(line);
iss >> box_z;

cout << "Box_X: " << box_x << "\n";
cout << "Box_Y: " << box_y << "\n";
cout << "Box_Z: " << box_z << "\n";

cout << "\nEnd Of File\n";

return 0;
}
}

contents of my data file:
9
23
3666

Problem: I run it, I pull the Box_X variable, but I don't get the
information from the second line nor the third. Just get 0 or NULL
I though maybe somewhere I would have to change lines in the getline but it
changes on it's own and pulls nothing from the next line,
maybe I need to reset a variable each time or something. Check it out, see
what's up.

Daniel



 
Reply With Quote
 
Jonathan Mcdougall
Guest
Posts: n/a
 
      11-23-2004
Daniel Moree wrote:
> I've messed around with it and checked out my copy of MSDN and can't quit
> figure out the error.
>
> this is the file:
> #include <iostream>
> #include <fstream>
> #include <sstream>
> #include <string>
>
> using namespace std;
>
> int main()
> {
> ifstream fin("main.dat");
> int box_x = 0, box_y = 0, box_z = 0;
>
> if(!fin ){
> cout << "There was an error with the file\n";
> return 1;
> } else {
> cout << "File found! Printing Contents:\n\n";
>
> string line;
> istringstream iss;
>
> getline(fin, line);
> iss.str(line);
> iss >> box_x;


iss.clear();

> getline(fin, line);
> iss.str(line);
> iss >> box_y;


iss.clear();

> getline(fin, line);
> iss.str(line);
> iss >> box_z;


iss.clear();

> cout << "Box_X: " << box_x << "\n";
> cout << "Box_Y: " << box_y << "\n";
> cout << "Box_Z: " << box_z << "\n";
>
> cout << "\nEnd Of File\n";
>
> return 0;
> }
> }
>
> contents of my data file:
> 9
> 23
> 3666
>
> Problem: I run it, I pull the Box_X variable, but I don't get the
> information from the second line nor the third. Just get 0 or NULL


Calling clear() on the stream resets its state to good. For a reason I
cannot explain (perhaps someone else could enlighten us), the compiler I
use (.net) seems to set the eof bit after reading from the
istringstream. I don't have other compilers handy to test, but calling
clear() should make it work (it does on my machine).

Jonathan
 
Reply With Quote
 
Karl Heinz Buchegger
Guest
Posts: n/a
 
      11-24-2004
Daniel Moree wrote:
>
> I've messed around with it and checked out my copy of MSDN and can't quit
> figure out the error.
>
> this is the file:
> #include <iostream>
> #include <fstream>
> #include <sstream>
> #include <string>
>
> using namespace std;
>
> int main()
> {
> ifstream fin("main.dat");
> int box_x = 0, box_y = 0, box_z = 0;
>
> if(!fin ){
> cout << "There was an error with the file\n";
> return 1;
> } else {
> cout << "File found! Printing Contents:\n\n";
>
> string line;
> istringstream iss;
>
> getline(fin, line);
> iss.str(line);
> iss >> box_x;
>
> getline(fin, line);


iss.clear();

> iss.str(line);
> iss >> box_y;
>
> getline(fin, line);


iss.clear();

> iss.str(line);
> iss >> box_z;
>
> cout << "Box_X: " << box_x << "\n";
> cout << "Box_Y: " << box_y << "\n";
> cout << "Box_Z: " << box_z << "\n";
>
> cout << "\nEnd Of File\n";
>
> return 0;
> }
> }
>
> contents of my data file:
> 9
> 23
> 3666
>
> Problem: I run it, I pull the Box_X variable, but I don't get the
> information from the second line nor the third.


You first nead to clear the stringstream.
The simplest thing is: Always use a fresh stringstream object. This
is much less an issue, if you simply put the reading of a value into
a function of its own. (Error handling omitted in the following)

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

using namespace std;

int ReadInt( ifstream& In )
{
int Tmp;
string line;

getline( In, line );
istringstream iss( line );
iss >> Tmp;

return Tmp;
}

int main()
{
ifstream fin("main.dat");
int box_x = 0, box_y = 0, box_z = 0;

if(!fin ){
cout << "There was an error with the file\n";
return EXIT_FAILURE;
}

cout << "File found! Printing Contents:\n\n";

box_x = ReadInt( fin );
box_y = ReadInt( fin );
box_z = ReadInt( fin );

cout << "Box_X: " << box_x << "\n";
cout << "Box_Y: " << box_y << "\n";
cout << "Box_Z: " << box_z << "\n";

cout << "\nEnd Of File\n";

return EXIT_SUCCESS;
}


--
Karl Heinz Buchegger
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
Daniel Moree
Guest
Posts: n/a
 
      11-24-2004
> #include <iostream>
> #include <fstream>
> #include <sstream>
> #include <string>
>
> using namespace std;
>
> int ReadInt( ifstream& In )
> {
> int Tmp;
> string line;
>
> getline( In, line );
> istringstream iss( line );
> iss >> Tmp;
>
> return Tmp;
> }
>
> int main()
> {
> ifstream fin("main.dat");
> int box_x = 0, box_y = 0, box_z = 0;
>
> if(!fin ){
> cout << "There was an error with the file\n";
> return EXIT_FAILURE;
> }
>
> cout << "File found! Printing Contents:\n\n";
>
> box_x = ReadInt( fin );
> box_y = ReadInt( fin );
> box_z = ReadInt( fin );
>
> cout << "Box_X: " << box_x << "\n";
> cout << "Box_Y: " << box_y << "\n";
> cout << "Box_Z: " << box_z << "\n";
>
> cout << "\nEnd Of File\n";
>
> return EXIT_SUCCESS;
> }


Thank you! I tried using iss.clear() and got nothing, I also tried
iss.remove() and a few other commands i though would work. I was thinking of
creating a class to do this for me. But I guess creating another function
will work and since It doesn't do much and resets everytime it's perfect.
Thanks for this. I really appriciate it guys!!!!

Daniel Moree



 
Reply With Quote
 
Karl Heinz Buchegger
Guest
Posts: n/a
 
      11-24-2004
Jonathan Mcdougall wrote:
>
> Calling clear() on the stream resets its state to good. For a reason I
> cannot explain (perhaps someone else could enlighten us),


Once you know, it is actually very simple.
As always, eof gets set when an attempt is made to read
past the end of the stream.

Now. When you do

iss >> box_y;

How does op>> detect that it has read the whole number:
* When a character is read from the stream that can no
longer belong to that number (such as eg. whitespace or
a character)
* Or when there is nothing more to read.

How is the second case detected: This is the tricky part.
It cannot be detected other then: when a character read operation
fails because of eof. Thus in order to figure out that the number
in the stream has been read completely, the op>> has to drive the
string into an eof state in this case (that is: the stream contains
only the number and nothing else).

--
Karl Heinz Buchegger
(E-Mail Removed)
 
Reply With Quote
 
Jonathan Mcdougall
Guest
Posts: n/a
 
      11-24-2004
Karl Heinz Buchegger wrote:
> Jonathan Mcdougall wrote:
>
>>Calling clear() on the stream resets its state to good. For a reason I
>>cannot explain (perhaps someone else could enlighten us),

>
>
> Once you know, it is actually very simple.
> As always, eof gets set when an attempt is made to read
> past the end of the stream.
>
> Now. When you do
>
> iss >> box_y;
>
> How does op>> detect that it has read the whole number:
> * When a character is read from the stream that can no
> longer belong to that number (such as eg. whitespace or
> a character)
> * Or when there is nothing more to read.
>
> How is the second case detected: This is the tricky part.
> It cannot be detected other then: when a character read operation
> fails because of eof. Thus in order to figure out that the number
> in the stream has been read completely, the op>> has to drive the
> string into an eof state in this case (that is: the stream contains
> only the number and nothing else).


Perfect explanation as usual, thank you.


Jonathan
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
writing binary file (ios::binary) Ron Eggler C++ 9 04-28-2008 08:20 AM
Reading and writing a binary file Chris Guenther Ruby 12 03-23-2005 05:30 PM
need help reading/writing binary Steve Bennett Perl 1 08-25-2004 06:08 PM
Reading/Writing pure binary files Daniel Gowans VHDL 2 06-12-2004 01:25 AM
URGENT: Reading from socket and writing into binary... HOW? Louis Java 6 10-15-2003 07:30 PM



Advertisments