Discussion:
File saving
(too old to reply)
Penny hapeny
2007-12-19 16:32:50 UTC
Permalink
Hi There,

I am trying to learn Builder from books etc, but have to abandon my efforts
from time to time, perhaps as much as 12 months and find I have forgotten
most of what I have learnt.

Anyway my present problem is with file saving and opening. which I have
bodged to make it work, but would like to do it properly. For example this
is my present code.

void __fastcall TForm1::SaveAs1Click(TObject *Sender)
{
char filename[85] = "Test3.txt" ;

FILE *fileptr;

if (SaveDialog1->Execute())
{
Label16->Caption = ExtractFileName(SaveDialog1->FileName); // If
I hover the mouse over FileName in this line when I have a break point
further along

// it shows what ever name I have
entered in the Save Dialog1 window
}

if ((fileptr = fopen(filename, "w")) == NULL)
// but if I do the same thing here it only shows filename as Test3.txt

// (obtained from the first line in
this function where char filename is defined).
{
Label16->Caption = "error: Cannot open file: Test3.txt";
exit (0);
}
Label16->Caption = "Writing data items to file: Test3.txt ";
fwrite(Grid, sizeof(Grid), 1, fileptr);


fclose(fileptr); /* Close file */

}

This works but only to save the results to Test3.txt The Execute function
brings up a Save Dialog box where I can enter a file name. but the example
only works or saves to Test3.txt

Any help to carry out what must be a simple task is appreciated.

Penny.
Remy Lebeau (TeamB)
2007-12-19 18:06:50 UTC
Permalink
Post by Penny hapeny
char filename[85] = "Test3.txt" ;
Why are you using a separate variable with a hard-coded filename? The whole
point of using a TSaveDialog is to allow the user to pick a filename to save
your data to, but you are not using the user's chosen filename at all.
Post by Penny hapeny
exit (0);
NEVER call exit() in a VCL application! It terminates the process
immediately and does not allow the VCL to clean up after itself. Given the
code you have shown, you probably don't want to terminate the process
anyway, but just exit from the SaveAs1Click() method. Use 'return' for that
instead of exit().
Post by Penny hapeny
This works but only to save the results to Test3.txt
The Execute function brings up a Save Dialog box where I can
enter a file name. but the example only works or saves to Test3.txt
Of course, because that is what hard-coded the code to do. You are
completely ignoring the value in the TSaveDialog's FileName property. Your
code should look more like the following instead:

void __fastcall TForm1::SaveAs1Click(TObject *Sender)
{
if( SaveDialog1->Execute() )
{
AnsiString FileName = SaveDialog1->FileName;

FILE *fileptr = fopen(FileName.c_str(), "w");
if( fileptr == NULL )
{
Label16->Caption = "error: Cannot open file: " + FileName;
return;
}

Label16->Caption = "Writing data items to file: " + FileName;
Label16->Update();

fwrite(Grid, sizeof(Grid), 1, fileptr);
fclose(fileptr);

Label16->Caption = "Data items successfully written to file: " +
FileName;
}
}


Gambit
Penny hapeny
2007-12-20 17:24:36 UTC
Permalink
Thank you Gambit, your code has worked. I had used the hard-coded filename
as my bodge to make the program work, as my effort to the contrary produced
errors I didn't understand.
Alas I thought from your advice and others I would be able to resolve the
OpenDialog routine, but have failed again.
This is my code

void __fastcall TForm1::Open1Click(TObject *Sender)
{
if(OpenDialog->Execute())
{
AnsiString FileName = OpenDialog->FileName;
Label16->Caption = "Opening data items from file: " + FileName;
Label16->Update();


Label16->Caption = ExtractFileName(OpenDialog->FileName);
Label16->Update();

ifstream in(FileName.c_str(), ios::in | ios::binary);
// This compiles Ok but no data from Grid is seen
ifstream in("Exaple01.txt", ios::in | ios::binary);
// This works and the data from Grid is seen, but file name has been given,
which defeats the exercise

in.read((char *) &Grid, sizeof Grid);
Label16->Caption = " Reading data from file " + FileName;
Label16->Update();
}
}

Grid is a 3 dimensional array

Thanks for any help
Penny
Post by Remy Lebeau (TeamB)
Post by Penny hapeny
char filename[85] = "Test3.txt" ;
Why are you using a separate variable with a hard-coded filename? The
whole point of using a TSaveDialog is to allow the user to pick a filename
to save your data to, but you are not using the user's chosen filename at
all.
Post by Penny hapeny
exit (0);
NEVER call exit() in a VCL application! It terminates the process
immediately and does not allow the VCL to clean up after itself. Given
the code you have shown, you probably don't want to terminate the process
anyway, but just exit from the SaveAs1Click() method. Use 'return' for
that instead of exit().
Post by Penny hapeny
This works but only to save the results to Test3.txt
The Execute function brings up a Save Dialog box where I can
enter a file name. but the example only works or saves to Test3.txt
Of course, because that is what hard-coded the code to do. You are
completely ignoring the value in the TSaveDialog's FileName property.
void __fastcall TForm1::SaveAs1Click(TObject *Sender)
{
if( SaveDialog1->Execute() )
{
AnsiString FileName = SaveDialog1->FileName;
FILE *fileptr = fopen(FileName.c_str(), "w");
if( fileptr == NULL )
{
Label16->Caption = "error: Cannot open file: " + FileName;
return;
}
Label16->Caption = "Writing data items to file: " + FileName;
Label16->Update();
fwrite(Grid, sizeof(Grid), 1, fileptr);
fclose(fileptr);
Label16->Caption = "Data items successfully written to file: "
+ FileName;
}
}
Gambit
Remy Lebeau (TeamB)
2007-12-20 17:52:51 UTC
Permalink
ifstream in(FileName.c_str(), ios::in | ios::binary); //
This compiles Ok but no data from Grid is seen
Then you are likely not specifying the correct filename in the OpenDialog to
begin with.
in.read((char *) &Grid, sizeof Grid);
You are not checking to make sure the ifstream was actually opened
successfully before then reading from it.


Gambit
Penny hapeny
2007-12-21 12:37:13 UTC
Permalink
Thank you for your help Gambit the following code now works Ok.

void __fastcall TForm1::Open1Click(TObject *Sender)
{
if(OpenDialog->Execute())
{
AnsiString FileName = OpenDialog->FileName;
Label16->Caption = "Opening data items from file: " + FileName;
Label16->Update();
Label16->Update();

Label16->Caption = ExtractFileName(OpenDialog->FileName);
Label16->Update();

FILE *fileptr = fopen(FileName.c_str(), "r");
if( fileptr == NULL )
{
Label16->Caption = "error: Cannot open file: " + FileName;
return;
}

ifstream in(FileName.c_str(), ios::in | ios::binary);
in.read((char *) &Grid, sizeof Grid);


Label16->Caption = " Reading Game data from file " +
FileName;
Label16->Update();
}
}

I have come across some functions that aren't given in any of my "C" or
"C++" reference books.Like Update() and Execute() I wonder if they are
Windows functions, and if you can point me to a web site that may have a
list if them all, I assume there are many more.

Many thanks for your help
Penny
Post by Remy Lebeau (TeamB)
ifstream in(FileName.c_str(), ios::in | ios::binary); //
This compiles Ok but no data from Grid is seen
Then you are likely not specifying the correct filename in the OpenDialog
to begin with.
in.read((char *) &Grid, sizeof Grid);
You are not checking to make sure the ifstream was actually opened
successfully before then reading from it.
Gambit
Asger Joergensen
2007-12-21 13:11:22 UTC
Permalink
Hi Penny
Post by Penny hapeny
I have come across some functions that aren't given in any of my "C" or
"C++" reference books.Like Update() and Execute() I wonder if they are
Windows functions, and if you can point me to a web site that may have a
list if them all, I assume there are many more.
Do You mean like:

Label16->Update();
OpenDialog->Execute();

??

If so, they are simply memberfunctions of e.g.
TLabel and TOpenDialog

and they can be found in the help under those types
among the methods of those types.

If not please give an example of the code where
You found the functions.

By the way I dont think You need all those:
Label16->Update();

The labels should update by them self when You
change the Caption, if they dont it is because
your program is doing something else and dont
have the time to check the messageque for new
messages.

If You want to force Your program to take care of
messages in the que You should use:

Application->ProcessMessages();

It is the same You would use if You have a loop
that takes a very long time to process and You
then want the chance to stop the loop

example:
You have global bool that can be changed if the user
press the escape key.

bool Stop = false;

somewhere in the program You have a long loop:

for(int i = 0; i < 429496729; ++i)
{
if(i % 10000 == 0)
{
Application->ProcessMessages();
if(Stop)break;
}
//do stuff
}

Application->ProcessMessages();
does what it says, it make the application take a
break from what it is doing and handle the messages
send to the Application.

Kind regards
Asger
Remy Lebeau (TeamB)
2007-12-21 18:01:27 UTC
Permalink
I have come across some functions that aren't given in any of my'
"C" or "C++" reference books.Like Update() and Execute()
I wonder if they are Windows functions
No, they are methods of VCL classes. Look in the VCL reference for them.


Gambit
Penny hapeny
2008-01-01 12:42:49 UTC
Permalink
Many Thanks Gambit & Asger

For your reply and example. I will study the Help information in Builder.
Happy New Year Penny
Post by Remy Lebeau (TeamB)
I have come across some functions that aren't given in any of my'
"C" or "C++" reference books.Like Update() and Execute()
I wonder if they are Windows functions
No, they are methods of VCL classes. Look in the VCL reference for them.
Gambit
Asger Joergensen
2007-12-19 18:11:50 UTC
Permalink
Hi Penny
Post by Penny hapeny
Hi There,
Label16->Caption = ExtractFileName(SaveDialog1->FileName);
Hope I understand You correctly.

ExtractFileName strips the path away so You have only
the filename left.

Try this: (not tested)

void __fastcall TForm1::SaveAs1Click(TObject *Sender)
{
String FileName = "Test3.txt";

if (SaveDialog1->Execute())
{
FileName = ExtractFileName(SaveDialog1->FileName);
Label16->Caption = FileName;
}

FILE *fileptr = fopen(FileName.c_str(), "w");

if( ! fileptr)
{
Label16->Caption = "error: Cannot open file: Test3.txt";
return;
}

Label16->Caption = "Writing ONE data item to file:\r\n" + FileName;

fwrite(Grid, sizeof(Grid), 1, fileptr);

fclose(fileptr); /* Close file */
}


p.s. What is Grid ?

Kind regards
Asger
Loading...