Board index » cppbuilder » TWriter and write binary data

TWriter and write binary data


2005-08-21 01:28:11 PM
cppbuilder104
I use a std::vector<BYTE>to store binary data.
I already use a TWriter object for writing/reading AnsiString and other
types of values autorized this class.
Now my need is to save/read too *BYTE data*:
Now how to store compressedData to TWriter, beacuse writer.Byte doesn't
exists ?
writer.Byte no where !
Sam
 
 

Re:TWriter and write binary data

On Sun, 21 Aug 2005 07:28:11 +0200, sam wrote:
Quote
Now how to store compressedData to TWriter, beacuse writer.Byte doesn't
exists ?

writer.Byte no where !
From the help
Do not directly create writer objects. Writers are automatically
created in stream object methods or in global routines that initiate
the streaming process. These include:
Given that you've already done so, have you looked at WriteChar() ?
--
liz
 

Re:TWriter and write binary data

"liz" < XXXX@XXXXX.COM >wrote in message:>
Quote
Given that you've already done so, have you looked at WriteChar() ?
It seems that writer.Write(..) is designed for that,beacause I can pass my
BYTE data and the count param ?
Sam
 

{smallsort}

Re:TWriter and write binary data

On Sun, 21 Aug 2005 19:17:00 +0200, sam wrote:
Quote
It seems that writer.Write(..) is designed for that,beacause I can pass my
BYTE data and the count param ?
What is your questions?
Read the help.
--
liz
 

Re:TWriter and write binary data

On Sun, 21 Aug 2005 15:18:14 -0400, liz wrote:
Quote
What is your questions?
Excuse me, I meant, What are you asking about?
--
liz
 

Re:TWriter and write binary data

sam wrote:
Quote
Now how to store compressedData to TWriter, beacuse writer.Byte
doesn't exists ?
It looks like you shouldn't be instantiating a TWriter class. Tbh I
have always used my own I/O functions and classes but from looking at
it TWriter is a low-level helper class. IIRC the correct VCL classes to
use are TStream and descendants like TFileStream.
As regards your other question I would have compress() return a
structure like this:
struct TCompressedData
{
DWORD RawDataCount;
std::vector<BYTE>CompressedData;
};
Writing this out is a little irritating because most of the vector is
stored on the heap. Dumping the structure out simply won't work. You
might as well think of 'CompressedData' as being a pointer in this
scenario.
The simplest way to resolve this is write the data out in two goes:
fileStream.Write( &compressedResult.RawDataCount,
sizeof( compressedResult.RawDataCount ) );
fileStream.Write( &( compressedResult.CompressedData[ 0 ] ),
compressedResult.CompressedData.size() );
Note that this then leads onto the question of how you will locate this
data when you read. If you are reading it sequentially then it's not
too difficult but for random access you need lookup table. If you are
compressing single strings then the table just needs to be a list of
seek offsets. To read a given string you'd use:
fileStream.Seek( Lookup[ LineNumber ] );
fileStream.Read( &compressedResult.RawDataCount,
sizeof( compressedRead.RawDataCount ) );
compressedRead.
CompressedData.resize( Lookup[ LineNumber+1 ]-
Lookup[ LineNumber ]-
sizeof( compressedResult.RawDataCount ) );
fileStream.Read( &( compressedRead[ 0 ] ),
compressedResult.RawDataCount );
One caveat:This won't work for the last line in the file because
'LineNumber+1' is invalid. You can resolve this by detecting that using
the file length instead of 'Lookup[ LineNumber+1 ]' or just have your
lookup table by one greater than needed or (perhaps best of all) have
the lookup table be an array of structures which record not just the
seek offset but also the length.
The latter idea allows you to modify the strings because they no longer
have to be in line order nor stored nose to tail.
All of this should be wrapped up in your own object with a simple
interface. Something like:
AnsiString MyCompressedStringReader.GetLine( DWORD LineNumber );
implementation details should be debugged then tucked away where they
won't scare anyone in the future :)
--
Andrue Cope [TeamB]
[Bicester, Uk]
info.borland.com/newsgroups/guide.html
 

Re:TWriter and write binary data

"Andrue Cope [TeamB]" wrote::
Quote
IIRC the correct VCL classes to use are TStream and descendants like
TFileStream.
I save TreeView to a file using a TWriter and load it by a TReader. So I
must use a TWriter.TReader for this, following my code:
TMemoryStream *S = new TMemoryStream();
writer= new TWriter( S, MAX_SIZE );
node = tv->Items->GetFirstNode();
writer->WriteListBegin();
while(node != NULL){
//1/ Node level
writer->WriteInteger(node->Level);
//2/ Node title
writer->WriteString(node->Text);
node= node->GetNext();
//==MY NEEDS HERE:
AnsiString sTemp = (AnsiString)reinterpret_cast<char *>( &(
compressedResult[ 0 ] ));
sTemp.SetLength(len);
writer->WriteString(sTemp);
//==
}
As you have seen, I already use TWriter for save/load TreeView content
because TWriter is easy and powerfull for my needs.
So, is there a risk of storing the content std::vector<BYTE>compressedData
to an AnsiString ?
If, so what is the other way using TWriter ?
Sam
 

Re:TWriter and write binary data

"sam" < XXXX@XXXXX.COM >wrote in message
Quote
I save TreeView to a file using a TWriter and load it by a TReader.
You should not be doing that. Use a TFileStream instead.
Quote
So I must use a TWriter.TReader for this
No, you do not. For example:
class TMyFileStream : public TFileStream
{
public:
__fastcall TMyFileStream(const AnsiString &FileName, Word Mode)
: TFileStream(FileName, Mode)
{
}
void __fastcall WriteInteger(int Value)
{
WriteBuffer(&Value, sizeof(int));
}
int __fastcall ReadInteger()
{
int Value;
ReadBuffer(&Value, sizeof(int));
return Value;
}
void __fastcall WriteString(const AnsiString &Str)
{
int len = Str.Length();
WriteInteger(len);
WriteBuffer(Str.c_str(), len);
}
AnsiString __fastcall ReadString()
{
int len = ReadInteger();
AnsiString Value;
if( len>0 )
{
Value.SetLength(len);
ReadBuffer(Value.c_str(), len);
}
return Value;
}
};
TMyFileStream *S = new TMyFileStream("c:\\somefile.data", fmCreate);
s->WriteInteger(tv->Items->Count);
node = tv->Items->GetFirstNode();
while( node )
{
S->WriteInteger(node->Level);
S->WriteString(node->Text);
//...
S->WriteInteger(compressedResult.size());
S->WriteBuffer(&compressedResult[0], compressedResult.size());
//...
node = node->GetNext();
}
delete S;
//...
TMyFileStream *S = new TMyFileStream("c:\\somefile.data", fmOpenRead |
fmShareDenyWrite);
tv->Items->Clear();
int count = s->ReadInteger();
for(int x = 0; x < count; ++x)
{
int iLevel = S->ReadInteger();
// create node as needed...
//...
node->Text = S->ReadString();
//...
compressedResult.resize(S->ReadInteger());
S->ReadBuffer(&compressedResult[0], compressedResult.size());
//...
}
delete S;
Gambit
 

Re:TWriter and write binary data

Gambit very thanks for this preciuous help !
Your code is being implemented.
Like Andrue, you have not win at the National Lottery to be a TeamB !
Your help is always a source of encouragement to continue.
Sam
 

Re:TWriter and write binary data

"sam" < XXXX@XXXXX.COM >wrote:
Quote

[...] you have not win at the National Lottery to be a TeamB !
I think his translator needs some work <g>.
~ JD