TFileStream Advice Please

Hi, am not very familiar with working with TFileStream or streams in general but am using XE5, and VCL and am working with a TFileStream to load/save data to a file, which seems to works great :) 

BUT am wanting to do more than the basics:

Scenario: I have multiple encodings of data-types, all of which are user selectable, and therefore I need to know the process used when decoding

A: I was considering how to tag my TFileStream, I guess I hope to add a tag like "ENC1"  to the start of the stream before beginning the encoding and saving process, but am unsure how

B: After decoding stream - I need to extract tag to know which further deconstruction/manipulation processes to use, and finally I need the remove tag if reverting data-file to its raw state.


I know I appear to need to be working with bytes, but can anyone point me at any articles, or helpful source-code which may help me with accomplishing this, Thanks in advance.
0
Dominic
7/28/2015 9:04:27 PM
embarcadero.delphi.general 4258 articles. 0 followers. Follow

4 Replies
558 Views

Similar Articles

[PageSpeed] 7

Dominic Mahon wrote:

> Hi, am not very familiar with working with TFileStream or streams in
> general but am using XE5, and VCL and am working with a TFileStream
> to load/save data to a file, which seems to works great :)
> 
> BUT am wanting to do more than the basics:
> 
> Scenario: I have multiple encodings of data-types, all of which are
> user selectable, and therefore I need to know the process used when
> decoding
> 
> A: I was considering how to tag my TFileStream, I guess I hope to add
> a tag like "ENC1"  to the start of the stream before beginning the
> encoding and saving process, but am unsure how

The tag is just data, you can write it to the stream and read it from
the stream like any other data item. If the tag is to be text you just
have to be aware of the fact that sizeof(char) is 2 in XE5, since the
default string type is UnicodeString.
  if Length(Tag) > 0 then
    aStream.WriteBuffer(Tag[1], Length(Tag)*Sizeof(Tag[1]));
 ... now write the data after the tag 

When reading or writing string types you need to pass the first element
of the string to write or read, since those take untyped parameters. An
untyped parameter actually passes the address of the item you specify,
and for a string type the address of the string variable itself is not
the address of the first character in the string (unlike for static
arrays or numeric data types).

If Tag is defined as AnsiString this would write 4 bytes to the stream,
if it is defined as String it would write 8. Tags in tagged file
formates usually use ASCII characters, so I would propose to use
Ansistring for the tags in your application.

For reading you have to know up front how long the tag in the file is,
and whether it will be unicode or ASCII. Let's assume you use tags of 4
ASCII characters:
  const
     TagLength = 4;
  var
     Tag: Ansistring;
  begin
     SetLength(Tag, TagLength);
     aStream.readBuffer(Tag[1],  TagLength);
     ... now read the data after the tag

> B: After decoding stream - I need to extract tag to know which
> further deconstruction/manipulation processes to use, and finally I

If your original file is encrypted or so you would first decrypt it
into a TMemoryStream (if it is not larger than a very few megabytes),
reset the memory stream's position to 0, and then read the tag as first
data item from the memory stream.

> need the remove tag if reverting data-file to its raw state.
 
For that you need to first read the complete tagged file into a memory
stream, move the memory stream position to the end of the tag
    aMemStream.Position := TagLength;

and then write the rest of the stream content to a new filestream. If
the data files you have to handle are too large to keep in memory you
have to do this with two filestreams, which means you have to create a
second file for the untagged version (with a new name, of course), then
perhaps delete the old file and rename the new to the old name (after
closing the two filestreams).

The above assumes that the tag is the first data item in the file, but
you could also put it at the end, of course. In this case you could
actually remove the tag just by setting the file length to the old
length minus TagLength. To read a tag you would first position the
stream to astream.size - TagLength. To write a tagged stream you would
first write the data and then the tag as last item.



-- 
Peter Below (TeamB)
0
Peter
7/29/2015 7:12:20 AM
Peter, Thank you for your helpful reply, could you humour me and see if I have understood you correctly:

my code based on your input:

constructor TMuddy.Create(OutputStream: TStream;InboundStream: TStream; Options: Integer);
var taglength:integer;
begin
  FOutputStream := OutputStream;
  reset();
  opts := Options;
  tag:='B91E';
  taglength:=Length(Tag)*Sizeof(Tag[1]);
  tag:='';
  if idtyp=False then   //encode
  begin
    case opts of
      0: tag:='B91E';
      7: tag:='MUDY';
    end;
    if Length(Tag) > 0 then
    FOutputStream.WriteBuffer(Tag[1], Length(Tag)*Sizeof(Tag[1]));
    FInputStream := InboundStream;
  end;
  //
  if idtyp=True then   //decode
  begin
    tag:='B91E'; //default
    SetLength(Tag,taglength);
    InboundStream.readBuffer(Tag[1], TagLength);
    opts:=0;
    if tag='MUDY' then
    begin
      opts:=7;
    end;
    InboundStream.Position:=taglength;
    if ((tag='MUDY') or (tag='B91E')) then
      FInputStream.CopyFrom(InboundStream, InboundStream.Size - InboundStream.Position)
    else FInputStream:=InboundStream;
    //
  end;

end;

Does that look right to you? 
Thanks once again
0
Dominic
7/29/2015 9:20:07 PM
Peter, Thank you for your helpful reply, could you humour me and see if I have understood you correctly:

my code based on your input:

constructor TMuddy.Create(OutputStream: TStream;InboundStream: TStream; Options: Integer);
var taglength:integer;
begin
  FOutputStream := OutputStream;
  reset();
  opts := Options;
  tag:='B91E';
  taglength:=Length(Tag)*Sizeof(Tag[1]);
  tag:='';
  if idtyp=False then   //encode
  begin
    case opts of
      0: tag:='B91E';
      7: tag:='MUDY';
    end;
    if Length(Tag) > 0 then
    FOutputStream.WriteBuffer(Tag[1], Length(Tag)*Sizeof(Tag[1]));
    FInputStream := InboundStream;
  end;
  //
  if idtyp=True then   //decode
  begin
    tag:='B91E'; //default
    SetLength(Tag,taglength);
    InboundStream.readBuffer(Tag[1], TagLength);
    opts:=0;
    if tag='MUDY' then
    begin
      opts:=7;
    end;
    InboundStream.Position:=taglength;
    if ((tag='MUDY') or (tag='B91E')) then
      FInputStream.CopyFrom(InboundStream, InboundStream.Size - InboundStream.Position)
    else FInputStream:=InboundStream;
    //
  end;

end;

Does that look right to you? 
Thanks once again
0
Dominic
7/29/2015 9:21:08 PM
Dominic Mahon wrote:

> Peter, Thank you for your helpful reply, could you humour me and see
> if I have understood you correctly:
> 
> my code based on your input:
> 
> constructor TMuddy.Create(OutputStream: TStream;InboundStream:
> TStream; Options: Integer); var taglength:integer;
> begin
 
A constructor should always call the constructor inherited from the
base class, even if it decends directly from
TObject and the inherited constructor does no do anything. It is a
useful habit to get into.

>   FOutputStream := OutputStream;
>   reset();
>   opts := Options;
>   tag:='B91E';
>   taglength:=Length(Tag)*Sizeof(Tag[1]);
>   tag:='';
>   if idtyp=False then   //encode
>   begin
>     case opts of
>       0: tag:='B91E';
>       7: tag:='MUDY';
>     end;
>     if Length(Tag) > 0 then
>     FOutputStream.WriteBuffer(Tag[1], Length(Tag)*Sizeof(Tag[1]));
>     FInputStream := InboundStream;
>   end;
>   //
>   if idtyp=True then   //decode
>   begin
>     tag:='B91E'; //default

You don't need to set a default here, it will be overwritten anyway.

>     SetLength(Tag,taglength);
>     InboundStream.readBuffer(Tag[1], TagLength);
>     opts:=0;
>     if tag='MUDY' then
>     begin
>       opts:=7;
>     end;
>     InboundStream.Position:=taglength;

That is not needed, the readBuffer statement will leave the input
stream at exactly this position anyway.

>     if ((tag='MUDY') or (tag='B91E')) then
>       FInputStream.CopyFrom(InboundStream, InboundStream.Size -
InboundStream.Position)

This will probably blow up in your face since you never create
FInputstream in this particular code branch.
     
 >   else FInputStream:=InboundStream;
>     //
>   end;
> 
> end;
> 
> Does that look right to you? 

I think your design has a general problem of keeping track of who is
responsible for the lifetimes of the streams used. Will the code that
calls the constructor later try to destroy the streams it passed as
parameters? Or will the object created free the FInputstream and
FOutputstream instances in its destructor? You have to be careful not
to create conflicts here. At best that may give you a memory leak, at
worst access violations if code tries to use an object that has been
freed elsewhere already.




> Thanks once again



-- 
Peter Below (TeamB)
0
Peter
7/29/2015 10:15:40 PM
Reply:

Similar Artilces:

General advice please!
Hi I have my SMTP server. It's working doing the basics.. I have a couple of forms that allow me to browse the DB tables and see what has come in from where on what account etc. Now, I'd like to run the SMTP server as a service but this raises another head scratching issue for me. If its run as a service, I still need to be able to login as admin and tinker with things. I figured I could do this using a TIdTCPServer / Client setup but then that means I can't use the delphi database components - as the DB (componentAce) is a local VCL in the program and not a DB ...

please please please
Name: Product: Firefox Summary: please please please Comments: could you please resolve this crashing. the browsers crashes so often... I'm watching streaming video and it crashes in the middle of it... which costs me. I don't want to exceed me bandwith with friggin rogers. they're a pain. Browser Details: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 From URL: http://hendrix.mozilla.org/ Note to readers: Hendrix gives no expectation of a response to this feedback but if you wish to provide one you mus...

Please Please Please
I have only been asking for 4 years but PLEASE include a setting at the accounts level that sets the default compose to plain text if the account of type NEWS. Its a PITA to have to recall or remember to change my compose to plain text manually! Andre, It appears that in the past few days you have not received a response to your posting. That concerns us, and has triggered this automated reply. Has your problem been resolved? If not, you might try one of the following options: - Do a search of our knowledgebase at http://support.novell.com/search/kb_index.jsp - Check a...

Please please please
Folks, Please can we stop the petty bickering about banning or not banning............... The points have been made and in my opinion this is not the place to carry on with it. Once again - PLEASE! Regards Ian _____________________________________ Ian Sargent Education & Training Consulting Services Ltd Tel/Fax: 01344 644579 Mobile: 07970 847197 email: ians@etcs.co.uk www: http://www.etcs.co.uk _____________________________________ "Ian Sargent" <ians@nospam_etcs.co.uk> wrote in news:af7d6c$2da6$1 @news.grc.com: > Please can we st...

Please, please, please ....
Name: Dean Talboys Email: deanatlouistalboysdotcom Product: Firefox Summary: Please, please, please .... Comments: Could you include a button on Firefox to register the currently viewed site as Firefox "Unfriendly"? I'm a developer of sophisticated Internet applications (check out http://www.psychl.com/ONE/cyclex.asp to see how much abuse a browser can take) and I always spend time to ensure my sites are IE and Firefox compatible. But I'm really frustrated at the number of sites that aren't Firefox compatible. You know, you get to the last screen of ...

PLEASE PLEASE PLEASE
Name: Nick Crain Email: n.crain_at_rogers.com Product: Firefox Summary: PLEASE PLEASE PLEASE Comments: Can you please include a rss feed indicator thing like IE 7 has. You know where every time you visit a page that has an rss feed available it beeps and then you can subscribe to it? That is such a handy feature. It's just too bad it's on a damn microsux product. please put it in firefox. Browser Details: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7 Nick Crain wrote: > Name: Nick Crain > Email: n.crain_at_r...

Please! Please! Please! Please! Help
I am very new to the Linux/Oracle/Perl world coming from a many many years of a Windows environment. I have self learned everything I know about this new environment. So far I have successfully installed Redhat 9 in an Intel box and have gotten Oracle 9I running correctly. I can run scripts via sqlplus, sqlldr etc. Perl (I think ver. 5.8.0) is running on the box and I can create and run scripts that do other processes but I have had no success in getting Perl to connect to the Oracle database to generate some reports. With my experience using MS-SQL there is no major issues w...

Please help, please, please
This is driving me crazy, I cannot find what is wrong with this thing. I have a custom module and after post back none of the following are processed : user, login, visibility, title, solpartmenu. None of it gets processed. Please help meYou died at the very end of your life Are you saying a skin, or a custom module. With custom modules you should not be dealing with tokens, I don't think they have anything to do with it. What module are you working with? No I am not using tokens, container skin is Classic skin that comes with DNN. I am talking about custom module. It has a text box a...

Please Please Please HELP!!!
I have posted this many times to no avail. I managed to publish the site somwhere despite being an intranet. I have published the site just in case I was not clear in explaining the prblem that I was having. Go to http://www.undg.ks.undp.org/test/login.aspx and login with userid: test password: test Click on 'search for cases' and then click on the search button (the dates are inserted automatically). Click on the paging and try to go to page 12,13,14,15 - any page really above page 11. Can you see what is happening? Below is the code that I am using. Please tell me wha...

Please Please Please help
I am trying to populate a second dropdownlist from the first. both dropdownlists are displayed inside the datagrid. I can populate the first one easily but my onselectedindexchanged event states: Object reference not set to an instance of an object. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.NullReferenceException: Object reference not set to an instance of an object. Source Error: Line 195...

Please Please Please help me out...
hello, our netware 6.0 file server can'nt connect the internet, we have a proxyserver with netware 6.0 and BM 3.8. can somebody please help me out i'm a newbie. hello, our netware 6.0 file server can'nt connect the internet, we have a proxyserver with netware 6.0 and BM 3.8. can somebody please help me out i'm a newbie. the file server ip is 192.20.71.1 the proxy ip is 192.20.71.252 akula_26@hotmail.com wrote: > our netware 6.0 file server can'nt connect the internet, we have a > proxyserver with netware 6.0 and BM 3.8. can somebody please hel...

Please advice me ...
Hello PB Gurus, I have 2 database stored in 2 different INFORMIXSERVER but in the same UNIX server. For example : db1@DBTCP1 db2@DBTCP2 My application will connect to db1. After some processing, I would like to extract some data from db2 but failed. It says that I don't have permission or database not found. Is it possible for me to connect to 2 INFORMIXSERVER ? Thanks in advance ! >I have 2 database stored in 2 different INFORMIXSERVER but in the same >UNIX server. For example : > >db1@DBTCP1 >db2@DBTCP2 > >My application will connect to d...

Please advice me (:
Hi all, I am struggling with this Error. While I am i am trying to connect to webservice, from my Web appln., its giving the error "The request failed with HTTP status 401: Unauthorized." I checked the DEFAULT WEB SITE and Folder , for the DIRECTORY SECURIT..it is enabled to ANONYMOUS and selected WINDOWS INTEGRATION.. Please somebody advice me ...(: Thanks ! Have a search for Credentials. Try doing something like (dont remember the exact syntax): webService.Credentials = Credentials.DefaultIntelligence is a burden.Jagdip Singh AjimalManchester (and yes, I am a...

Please advice me ...
Hello PB Gurus, I have 2 database stored in 2 different INFORMIXSERVER but in the same UNIX server. For example : db1@DBTCP1 db2@DBTCP2 My application will connect to db1. After some processing, I would like to extract some data from db2 but failed. It says that I don't have permission or database not found. Is it possible for me to connect to 2 INFORMIXSERVER ? Thanks in advance ! Saimee wrote: > > Hello PB Gurus, > > I have 2 database stored in 2 different INFORMIXSERVER but in the same > UNIX server. For example : > > db1@DBTCP1 >...

Web resources about - TFileStream Advice Please - embarcadero.delphi.general

1.76复古传奇玩家交流-1.76复古传奇_新开传奇私服_网通传奇私服-xiao114传奇私服发布网
xiao114,1.76复古传奇,发布网提供最全的1.76复古传奇玩家交流信息。

Resources last updated: 1/6/2016 10:05:51 PM