Board index » cppbuilder » ok, step to step to write and read from a owner file

ok, step to step to write and read from a owner file


2003-08-11 05:13:39 PM
cppbuilder112
I would make a custom file contained some information, that is:
a ANSI string of 20 characters, just after some number of 6 digits then 4
digits for an array dimension, now an array (i get its dimension from the
previuous 4 digits), just at the end a file bitmap...
How is so nice to explain me (giving me a little of code) how save and so
read these datas?
 
 

Re:ok, step to step to write and read from a owner file

"b" <borland.public.cppbuilder.vcl.components.using>wrote:
Quote
I would make a custom file contained some information, that is:
Define a structure that you can use as a header to easily
read/write to the file:
struct MyHeader
{
char MyString[20]; // string of 20 characters
int SomeNumber; // some number of 6 digits
int Dimension[4]; // 4 digits for an array dimension
};
To write to the file, open it and position at the start. Then
write the header, the array and finally the Bitmap. The resulting
file will look like this:
Header Data
Array Data
Bitmap
To read it back, you simply do it in reverse. Open the file
and position to the start of the file. Read the header,
allocate the array, read the array and finally read the bitmap.
~ JD
 

Re:ok, step to step to write and read from a owner file

I'm tring with this way.
To Write:
void __fastcall TForm1::Saveas1Click(TObject *Sender)
{
if(SaveDialog1->Execute() == mrOk)
{
EncodeFileProject(Image->Picture->Bitmap, SaveDialog1->FileName);
}
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::EncodeFileProject(Graphics::TBitmap *bitmapDrawed,
AnsiString fileNameProject)
{
String fExtension = ExtractFileExt(fileNameProject);
if ((fExtension != ".prj") && (fExtension != ".PRJ"))
{
fileNameProject = fileNameProject + ".PRJ";
}
std::auto_ptr<TFileStream>EncStream(new TFileStream(fileNameProject,
fmCreate));
// write the name
char *nameTemp = new char[Form2->getNameLen()+1];
int v;
for(v = 0; v<Form2->getNameLen(); v++)
{
nameTemp[v] = Form2->getName(v);
}
EncStream->Position = 0;
EncStream->Write(nameTemp, 20);
delete nameTemp;
// write w and h (some digits of example)
char wtemp[3];
itoa(w, wtemp, 10);
EncStream->Position = 20;
EncStream->Write(wtemp, 3);
char htemp[3];
itoa(h, htemp, 10);
EncStream->Position = 23;
EncStream->Write(htemp, 3);
//write the bitmap size
TMemoryStream* BitmapStream = new TMemoryStream();
BitmapStream->Position = 0;
bitmapDrawed->PixelFormat = pf32bit;
bitmapDrawed->SaveToStream(BitmapStream);
EncStream->Position = 26;
//Size = bitmapDrawed->Height * bitmapDrawed->Width *
bitmapDrawed->PixelFormat;
Size = BitmapStream->Size;
EncStream->Write(&BitmapStream, Size);
// write the map array
EncStream->Position = 36;
EncStream->Write(GArray, sizeof(int)*w*h);
// write the bitmap
BitmapStream->Position = 0;
EncStream->Position = (36 + (sizeof(int)*w*h));
EncStream->CopyFrom(BitmapStream, BitmapStream->Size);
delete BitmapStream;
}
Now Reading:
void __fastcall TForm1::OpenProjectClick(TObject *Sender)
{
int res = 0;
Application->NormalizeTopMosts();
if(Modifiedbool) res = Application->MessageBox("Save the current
Project?", "Program", MB_YESNOCANCEL);
Application->RestoreTopMosts();
//if(res == 6) ;//call the function that save and close the current
project
if((res==6) || (res==7) || (res==0))
{
if(OpenDialog1->Execute() == mrOk)
{
int width = atoi(EncodeSize(OpenDialog1->FileName, 20).c_str()); //
change with w
int height = atoi(EncodeSize(OpenDialog1->FileName, 23).c_str()); //
change with h
std::auto_ptr<TFileStream>EncStream(new
TFileStream(OpenDialog1->FileName, fmOpenRead));
//EncStream->Position = 0;
delete GArray;
GArray = new int[width*height];
EncStream->Position = 26;
EncStream->Read(GArray, sizeof(int)*width*height);
//int thisPosition = 26 + sizeof(int)*width*height; /**/
Graphics::TBitmap *pBitmapTemp = new Graphics::TBitmap();
TMemoryStream* BitmapStream = new TMemoryStream();
EncStream->Position = (36 + (sizeof(int)*w*h));
EncStream->Read(&BitmapStream, Size);
BitmapStream->Position = 0;
pBitmapTemp->LoadFromStream(BitmapStream);/**/
BitBlt(Image->Canvas->Handle, 0, 0, w*32, h*32,
pBitmapTemp->Canvas->Handle, 0, 0, SRCCOPY);
TRect const RUpdate(0, 0, 525, 352);
RedrawWindow(Panel->Handle, &RUpdate, NULL, RDW_INVALIDATE |
RDW_UPDATENOW);
delete BitmapStream;
delete pBitmapTemp;
}
}
}
//--------------------------------------------------------------------------
-
AnsiString __fastcall TForm1::EncodeSize(AnsiString ProjectOpenPath, int n)
{
AnsiString i;
i.SetLength(4);
std::auto_ptr<TFileStream>EncStream(new TFileStream(ProjectOpenPath,
fmOpenRead));
EncStream->Position = n;
EncStream->Read(i.c_str(), 3);
return i;
}
"JD" < XXXX@XXXXX.COM >ha scritto nel messaggio
Quote

"b" <borland.public.cppbuilder.vcl.components.using>wrote:
>I would make a custom file contained some information, that is:

Define a structure that you can use as a header to easily
read/write to the file:

struct MyHeader
{
char MyString[20]; // string of 20 characters
int SomeNumber; // some number of 6 digits
int Dimension[4]; // 4 digits for an array dimension
};


To write to the file, open it and position at the start. Then
write the header, the array and finally the Bitmap. The resulting
file will look like this:

Header Data
Array Data
Bitmap

To read it back, you simply do it in reverse. Open the file
and position to the start of the file. Read the header,
allocate the array, read the array and finally read the bitmap.

~ JD

 

{smallsort}

Re:ok, step to step to write and read from a owner file

Sorry i forget, what i wrong? I get wrong values of array when i read from
the file that is: at the place of 20, 3, 5... values, i get 242342, 5465242,
234234, and i can't see the new bitmap when open the project and read the
bitmap information from this.
 

Re:ok, step to step to write and read from a owner file

"b" <borland.public.cppbuilder.vcl.components.using>wrote:
Quote
I'm tring with this way. [...]
One problem was that you were not reading the file in the same
order as you created it. You had the array and bitmap order
reversed.
Another problem was a memory leak when you deleted the array
and there is a possible problem with 'w' and 'h'. You didn't
show where they were defined and initialized to their current
value. Also note that one function has been removed completely.
HTH
~ JD
// in the header
struct MyHeaderStructure
{
char Name[20];
int Width;
int Height;
int BitmapSize;
};
//-------------------------------------------------------------
void __fastcall TForm1::Saveas1Click(TObject *Sender)
{
if( SaveDialog1->Execute() )
{
EncodeFileProject( Image->Picture->Bitmap, SaveDialog1->FileName );
}
}
//------------------------------------------------------------
void __fastcall TForm1::EncodeFileProject(Graphics::TBitmap *bitmapDrawed, AnsiString fileNameProject)
{
MyHeaderStructure Header;
memset( Header, 0, sizeof(MyHeaderStructure) );
String tmp = ExtractFileExt( fileNameProject );
fileNameProject = fileNameProject + ".PRJ";
tmp = Form2->GetName();
strncpy( Header->Name, tmp.c_str(), 19 );
Header->Width = w;
Header->Height = h;
TMemoryStream* BitmapStream = new TMemoryStream();
BitmapStream->Position = 0;
bitmapDrawed->PixelFormat = pf32bit;
bitmapDrawed->SaveToStream( BitmapStream );
BitmapStream->Position = 0;
Header->BitmapSize = BitmapStream->Size;
std::auto_ptr<TFileStream>EncStream( new TFileStream( fileNameProject, fmCreate ) );
EncStream->Position = 0;
EncStream->Write( Header, sizeof(MyHeaderStructure) );
EncStream->Write( GArray, sizeof(int) * w * h );
EncStream->CopyFrom(BitmapStream, BitmapStream->Size);
delete BitmapStream;
}
//-------------------------------------------------------------
void __fastcall TForm1::OpenProjectClick(TObject *Sender)
{
int res = 0;
MyHeaderStructure Header;
memset( Header, 0, sizeof(MyHeaderStructure) );
Application->NormalizeTopMosts();
if( Modifiedbool ) res = Application->MessageBox("Save the current Project?", "Program", MB_YESNOCANCEL);
Application->RestoreTopMosts();
if( res == 6 || res == 7 || res == 0 )
{
if( OpenDialog1->Execute() )
{
delete [] GArray;
std::auto_ptr<TFileStream>EncStream( new TFileStream( OpenDialog1->FileName, fmOpenRead ) );
EncStream->Position = 0;
EncStream->Read( Header, sizeof(MyHeaderStructure) );
GArray = new int[ Header->Width * Header->Height ];
EncStream->Read( GArray, sizeof(int) * Header->Width * Header->Height );
Graphics::TBitmap *pBitmapTemp = new Graphics::TBitmap();
TMemoryStream* BitmapStream = new TMemoryStream();
BitmapStream->Position = 0;
EncStream->Read( &BitmapStream, Header->BitmapSize );
BitmapStream->Position = 0;
pBitmapTemp->LoadFromStream( BitmapStream );
// where is w and h defined?
BitBlt(Image->Canvas->Handle, 0, 0, w*32, h*32, pBitmapTemp->Canvas->Handle, 0, 0, SRCCOPY);
TRect const RUpdate(0, 0, 525, 352);
RedrawWindow(Panel->Handle, &RUpdate, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
delete BitmapStream;
delete pBitmapTemp;
}
}
}
 

Re:ok, step to step to write and read from a owner file

using this: memset( Header, 0, sizeof(MyHeaderStructure) );
i get an error:
[C++ Error] Program.cpp(882): E2034 Cannot convert 'MyHeaderStructure' to
'void *'
[C++ Error] Program.cpp(882): E2342 Type mismatch in parameter '__s' (wanted
'void *', got 'MyHeaderStructure')
"JD" < XXXX@XXXXX.COM >ha scritto nel messaggio
Quote

"b" <borland.public.cppbuilder.vcl.components.using>wrote:
>I'm tring with this way. [...]

One problem was that you were not reading the file in the same
order as you created it. You had the array and bitmap order
reversed.

Another problem was a memory leak when you deleted the array
and there is a possible problem with 'w' and 'h'. You didn't
show where they were defined and initialized to their current
value. Also note that one function has been removed completely.

HTH

~ JD



// in the header
struct MyHeaderStructure
{
char Name[20];
int Width;
int Height;
int BitmapSize;
};
//-------------------------------------------------------------
void __fastcall TForm1::Saveas1Click(TObject *Sender)
{
if( SaveDialog1->Execute() )
{
EncodeFileProject( Image->Picture->Bitmap,
SaveDialog1->FileName );
}
}
//------------------------------------------------------------
void __fastcall TForm1::EncodeFileProject(Graphics::TBitmap *bitmapDrawed,
AnsiString fileNameProject)
{
MyHeaderStructure Header;
memset( Header, 0, sizeof(MyHeaderStructure) );
String tmp = ExtractFileExt( fileNameProject );
fileNameProject = fileNameProject + ".PRJ";

tmp = Form2->GetName();
strncpy( Header->Name, tmp.c_str(), 19 );
Header->Width = w;
Header->Height = h;

TMemoryStream* BitmapStream = new TMemoryStream();
BitmapStream->Position = 0;
bitmapDrawed->PixelFormat = pf32bit;
bitmapDrawed->SaveToStream( BitmapStream );
BitmapStream->Position = 0;

Header->BitmapSize = BitmapStream->Size;

std::auto_ptr<TFileStream>EncStream( new TFileStream( fileNameProject,
fmCreate ) );
EncStream->Position = 0;
EncStream->Write( Header, sizeof(MyHeaderStructure) );
EncStream->Write( GArray, sizeof(int) * w * h );
EncStream->CopyFrom(BitmapStream, BitmapStream->Size);

delete BitmapStream;
}
//-------------------------------------------------------------
void __fastcall TForm1::OpenProjectClick(TObject *Sender)
{
int res = 0;
MyHeaderStructure Header;
memset( Header, 0, sizeof(MyHeaderStructure) );

Application->NormalizeTopMosts();
if( Modifiedbool ) res = Application->MessageBox("Save the current
Project?", "Program", MB_YESNOCANCEL);
Application->RestoreTopMosts();

if( res == 6 || res == 7 || res == 0 )
{
if( OpenDialog1->Execute() )
{
delete [] GArray;
std::auto_ptr<TFileStream>EncStream( new TFileStream(
OpenDialog1->FileName, fmOpenRead ) );
EncStream->Position = 0;
EncStream->Read( Header, sizeof(MyHeaderStructure) );

GArray = new int[ Header->Width * Header->Height ];
EncStream->Read( GArray, sizeof(int) * Header->Width *
Header->Height );

Graphics::TBitmap *pBitmapTemp = new Graphics::TBitmap();
TMemoryStream* BitmapStream = new TMemoryStream();
BitmapStream->Position = 0;
EncStream->Read( &BitmapStream, Header->BitmapSize );
BitmapStream->Position = 0;
pBitmapTemp->LoadFromStream( BitmapStream );

// where is w and h defined?
BitBlt(Image->Canvas->Handle, 0, 0, w*32, h*32,
pBitmapTemp->Canvas->Handle, 0, 0, SRCCOPY);
TRect const RUpdate(0, 0, 525, 352);
RedrawWindow(Panel->Handle, &RUpdate, NULL, RDW_INVALIDATE |
RDW_UPDATENOW);

delete BitmapStream;
delete pBitmapTemp;
}
}
}

 

Re:ok, step to step to write and read from a owner file

JD it works fine, but the only problem is loading the bitmap, i get a blank
bitmap inside a TImage, why?
this is the file saved:
filename   6@ 2 "  BM6@ 6 ( @ @ 
@ ??????????????
??????????????????
???????????????????
???????????????????
???????????????????
?????? ????????????
???????????????????
o o o o o p p p p p q q q q q r r r r
r s s s s s t t t t u u u ??T T T
T T T T T T T T T T T T T T T T T T T
T T T T T T T o o o o o p p p p p q q
q q q r r r r r s s s s s t t t t u u
u ??T T T T T T T T T T T T T T T
T T T T T T T T T T T T T T o o o o
............................. ans so on.......
 

Re:ok, step to step to write and read from a owner file

"gif" < XXXX@XXXXX.COM >wrote:
Quote
[...] problem is loading the bitmap, i get a blank bitmap
inside a TImage, why?
It's difficult to say with any certainty what's wrong. The
file writing/reading just writes and reads what's there. Most
likely the bitmap is getting messed up as you manipulate it.
Try adding a second image on the form and assign the bitmap to
it as you go. Use ShowMessage( "Step1" ) ect after each step
so that you can get a look at the image and try to pinpoint
where it's going wrong.
~ JD
 

Re:ok, step to step to write and read from a owner file

Hi JD,
i did just as you told me, that is using a new TImage and displaying the
bitmap loaded from the file, but unluckly also it is blank...
I think it depends by:
void __fastcall TForm1::Saveas1Click(TObject *Sender)
{
if(SaveDialog1->Execute())
{
EncodeFileProject(Image->Picture->Bitmap, // <-- THIS
SaveDialog1->FileName);
}
}
are we sure that it tranfers a real Bitmap to the function EncodeFileProject
??
when i save the file and i open it with a Notepad i can read the lines i
showed you in the post above.
 

Re:ok, step to step to write and read from a owner file

ok JD and all the others been following this posts...
i corrected the error:
i write the bitmap stream using this:
EncStream->CopyFrom(BitmapStream, BitmapStream->Size);
so i must read using this directly:
pBitmapTemp->LoadFromStream( EncStream.get() ); // and it works!!! : )
now the question is:
using EncStream.get() i get all the streaming saved into the file starting
from the cursor position, but if i don't want read all but just a size? for
example:
pBitmapTemp->LoadFromStream( EncStream.get() , Header->BitmapSize); // ????
how can i do???
 

Re:ok, step to step to write and read from a owner file

"gif" < XXXX@XXXXX.COM >wrote:
Quote
[...] now the question is: using EncStream.get() i get all
the streaming saved into the file starting from the cursor
position, but if i don't want read all but just a size?
Why would you want to do that? Only use .get() to grab the
bitmap. The bitmap is at the end of the file and you want to
grab all of it at once anyway.
The only reason I can think that this would be a problem would
be if you have multiple instances of your data in one file. If
that is so, just use one more stream and copy the bitmap to
it. Then you'll be able to use LoadFromStream again.
~ JD
 

Re:ok, step to step to write and read from a owner file

The reason is that i would write 2 bitmap images (different) inside the
file.
So how can i do?
Why futhermore if i use Stream to read the bitmap it doesn't work, then if i
use directly EncStream with its method .get() it do?
"JD" < XXXX@XXXXX.COM >ha scritto nel messaggio
Quote

"gif" < XXXX@XXXXX.COM >wrote:
>[...] now the question is: using EncStream.get() i get all
>the streaming saved into the file starting from the cursor
>position, but if i don't want read all but just a size?

Why would you want to do that? Only use .get() to grab the
bitmap. The bitmap is at the end of the file and you want to
grab all of it at once anyway.

The only reason I can think that this would be a problem would
be if you have multiple instances of your data in one file. If
that is so, just use one more stream and copy the bitmap to
it. Then you'll be able to use LoadFromStream again.

~ JD

 

Re:ok, step to step to write and read from a owner file

"gif" < XXXX@XXXXX.COM >wrote:
Quote
The reason is that i would write 2 bitmap images (different)
inside the file.
I thought as much.
Quote
So how can i do?
Well we know that the data is there and that you were able to
get it out correctly using:
pBitmapTemp->LoadFromStream( EncStream.get() )
My problem is that the code that you posted didn't show
getting two bitmaps OR writting them for that matter. So...
I'll just use the code that you did post. Try the following:
TMemoryStream* BitmapStream = new TMemoryStream();
BitmapStream->Position = 0;
BitmapStream->CopyFrom( EncStream, Header.BitmapSize );
BitmapStream->Position = 0;
pBitmapTemp->LoadFromStream( BitmapStream );
//reposition BitmapStream ONLY if you need to use it again
BitmapStream->Position = 0;
//Position EncStream ONLY if you need more after the bitmap
EncStream->Position = sizeof( MyHeaderStructure ) + ( sizeof(int) * Header.Width * Header.Height );
~ JD
 

Re:ok, step to step to write and read from a owner file

tnx JD, i will try later, i will leave to know this night, really tnx!
 

Re:ok, step to step to write and read from a owner file

I get this error:
[C++ Error] Editor.cpp(951): E2034 Cannot convert 'auto_ptr<TFileStream>' to
'TStream *'
[C++ Error] Editor.cpp(951): E2342 Type mismatch in parameter 'Source'
(wanted 'TStream *', got 'auto_ptr<TFileStream>')
at this line:
BitmapStream->CopyFrom( EncStream, Header.BitmapSize );
becouse EncStream is a std::auto_ptr<TFileStream>EncStream( new
TFileStream( OpenDialog1->FileName, fmOpenRead ) );
what do u suggest me to do?
"JD" < XXXX@XXXXX.COM >ha scritto nel messaggio
Quote

"gif" < XXXX@XXXXX.COM >wrote:
>The reason is that i would write 2 bitmap images (different)
>inside the file.

I thought as much.

>So how can i do?

Well we know that the data is there and that you were able to
get it out correctly using:

pBitmapTemp->LoadFromStream( EncStream.get() )

My problem is that the code that you posted didn't show
getting two bitmaps OR writting them for that matter. So...
I'll just use the code that you did post. Try the following:

TMemoryStream* BitmapStream = new TMemoryStream();
BitmapStream->Position = 0;
BitmapStream->CopyFrom( EncStream, Header.BitmapSize );
BitmapStream->Position = 0;
pBitmapTemp->LoadFromStream( BitmapStream );

//reposition BitmapStream ONLY if you need to use it again
BitmapStream->Position = 0;

//Position EncStream ONLY if you need more after the bitmap
EncStream->Position = sizeof( MyHeaderStructure ) + ( sizeof(int) *
Header.Width * Header.Height );

~ JD