TFiler???

Hi!

I am writing an application which requires saving of graphics, strings, integers and other binary data into a file. How do I do this, I would prefer not to have the data indexed but rather retrieved by keyword. (eg. MainPic for the data associated with a TStream or something along those lines) Is this possible? thanks for help
captainklinkAsked:
Who is Participating?
 
EpsylonConnect With a Mentor Commented:
Glad you like it!

Now you can grade me  :o)
0
 
EpsylonCommented:
Delphi provides things like;

TGraphic.SaveToFile
TJPEGImage.SaveToFile
TListBox.SaveToFile
TStream.SaveToFile  (TMemoryStream, TStringStream, etc.)



0
 
kretzschmarCommented:
hi captainklink,

i would do this in a database-table with keyword-field, storedtyp-field, and a blobfiled for all what you want to store( or just a string which points to a filename).

meikl
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
333Commented:
Or you can use TSream.WriteComponentRes and TSream.ReadComponentRes to save whole component into file or  TSream.WriteComponentRes and TSream.ReadComponentRes to save into Windows resource file.

A.
0
 
EpsylonCommented:
Captainclick, can you be more specific on what you want?

This for exmaple converts a BMP to JPG:

uses jpeg;

var p: TPicture;
    j: TJPEGImage;
begin
  p := TPicture.Create;
  p.LoadFromFile('Image.bmp');
  j := TJPEGImage.Create;
  j.Assign(p.Bitmap);
  j.SaveToFile('Image.jpg');
  j.Free;
  p.Free;
end;
0
 
captainklinkAuthor Commented:
epsylon - i would like to save all of these things into the same file, not seperate ones,

kretzschmar - that means i would have to setup a database wouldn't it. I don't want to have to use a database, or don't I have to? i don't really know anything about databases.

333 - that sounds like what i want to do, but how do you do that at run-time, i can't figure it out?

...
basically i want to know how programs save their data into a file. The data saved has to be dynamic, ie not using the file of [Record] method, because I'll want to save things like RichText data, etc. Thanks for the help  CK
0
 
EpsylonCommented:
Captainklink, instead of SaveToFile you can use SaveToStream (i.e. TFileStream) to save pictures, data, Strings etc. to one single stream. So you will have one file.

0
 
EpsylonCommented:
But I reading it back again will not work this way because TPicture.ReadFromStream does not know how big the picture in the stream is and load the entire stream from the current position.
In this case you should use WriteComponentRes and ReadComponentRes.
0
 
captainklinkAuthor Commented:
epsylon - How do you use Write/ReadComponentRes? I've tried but I can't figure it out.
0
 
EpsylonCommented:
Sorry, I just figured out that WriteComponentRes and ReadComponentRes won't work with picture objects. It's only for descendants of TComponent. So we have to devide the stream into tags ourselves but that won't be a big problem I think.

Before writing each part in the stream, write a tag. The tag must contain an identifier and length. The identifier refers to what to be found in the next part of the stream: a picture or other data.
When reading it all back from the stream, the identifier tells how to process the next 'length' bytes in the stream.
Use the CopyFrom method here.


0
 
captainklinkAuthor Commented:
thanks alot epsylon
0
 
EpsylonCommented:
If you want I can work it out for you but you'll have to wait a day. Have other things to right now.
0
 
333Commented:
"I just figured out that WriteComponentRes and ReadComponentRes won't work with picture objects. It's only for descendants of TComponent."
Epsylon, yes you can't write TBitmap with WriteComponentRes because TBitmap is descendant of TGraphic, not TComponent, but you can allways assign bitmap to TImage and then write whole TImage component.

A.


0
 
captainklinkAuthor Commented:
Thanks everyone, that would be great epsylon if you could.

kretzschmar mentioned above about using TFields, that does involve using a database doesn't it? Is there a way of writing a field or table or whatever to a stream? It's pretty weird that there's nothing like Write/ReadComponentRes available. Well thanks everyone, especially Epsylon...
0
 
JaccoCommented:
For writing binary files I always you TWriter/TReader (descendants of TFiler). The work with any stream and support "type-safe" storage.

If you want info let me know

Regards Jacco


0
 
EpsylonCommented:
Hi, I am making progress and I think it will be finished by tomorrow.
0
 
EpsylonCommented:
Sorry for the delay but here it is:
0
 
EpsylonCommented:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, jpeg, ExtCtrls;

type
  TForm1 = class(TForm)
    Write: TButton;
    Read: TButton;
    procedure WriteClick(Sender: TObject);
    procedure ReadClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses ObjectStream;

{$R *.DFM}

procedure TForm1.WriteClick(Sender: TObject);
var os: TObjFileStream;
    j: TJPEGImage;
    b: TBitmap;
    a: array[0..9] of Extended;
    i: Integer;
begin
  os := TObjFileStream.Create('TestFile', fmCreate or fmOpenWrite);

  os.WriteInteger(24);

  Randomize;
  for i := 0 to 9 do
    a[i] := random;
  os.WriteBinary(a[0], sizeof(a));

  j := TJPEGImage.Create;
  j.LoadFromFile('jpgimage.jpg');
  os.WriteJPEGImage(j);
  j.Free;

  b := TBitmap.Create;
  b.LoadFromFile('bmpimage.bmp');
  os.WriteBMPImage(b);
  b.Free;

  os.WriteString('Hey dude, this works!');

  os.Free;
end;

procedure TForm1.ReadClick(Sender: TObject);
var os: TObjFileStream;
    j: TJPEGImage;
    b: TBitmap;
    s: String;
    a: array[0..9] of Extended;
    i: Integer;
begin
  os := TObjFileStream.Create('TestFile', fmOpenRead);

  while os.NextID <> osEOF do
  begin
    case os.ID of
      osJPEGImage:
        begin
          j := TJPEGImage.Create;
          os.ReadJPEGImage(j);
          j.SaveToFile('NewImage.jpg');
          j.Free;
        end;
      osBMPImage:
        begin
          b := TBitmap.Create;
          os.ReadBMPImage(b);
          b.SaveToFile('NewImage.bmp');
          b.Free;
        end;
      osString:
        begin
          s := os.ReadString;
          ShowMessage(s);
        end;
      osBinary:
        begin
          os.ReadBinary(a, os.IDSize);
          s := '';
          for i := 0 to 9 do
            s := s + FloatToStr(a[i]) + #13#10;
          ShowMessage(s);
        end;
      osInteger:
        begin
          i := os.ReadInteger;
          ShowMessage(IntToStr(i));
        end;
      else os.Skip;
    end;
  end;
  os.Free;
end;

end.
0
 
EpsylonCommented:
unit ObjectStream;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, jpeg, ExtCtrls, Math;

type
  TStreamObj = (osEOF, osString, osJPEGImage, osBMPImage, osInteger, osBinary);

  TObjFileStream = class(TFileStream)
  private
    { Private declarations }
  public
    { Public declarations }
    ID: TStreamObj;
    IDSize: Integer;
    function NextID: TStreamObj;
    function Skip: Integer;
    function ReadJPEGImage(image: TJPEGImage): Integer;
    function WriteJPEGImage(image: TJPEGImage): Integer;
    function ReadBMPImage(image: TBitmap): Integer;
    function WriteBMPImage(image: TBitmap): Integer;
    function ReadString: String;
    function WriteString(s: String): Integer;
    function ReadInteger: Integer;
    function WriteInteger(Value: Integer): Integer;
    function ReadBinary(var data; count: Integer): Integer;
    function WriteBinary(var data; count: Integer): Integer;
  end;

implementation

{ TObjFileStream }

function TObjFileStream.NextID: TStreamObj;
begin
  if Read(ID, sizeof(ID)) = 0 then
  begin
    ID := osEOF;
    IDSize := 0;
  end
  else
    Read(IDSize, sizeof(IDSize));
  Result := ID;
end;

function TObjFileStream.ReadBinary(var data; count: Integer): Integer;
begin
  Result := Read(data, count));
end;

function TObjFileStream.ReadBMPImage(image: TBitmap): Integer;
var ms: TMemoryStream;
begin
  ms := TMemoryStream.Create;
  result := ms.CopyFrom(Self, IDSize);
  ms.Seek(0, soFromBeginning);
  image.LoadFromStream(ms);
  ms.Free;
end;

function TObjFileStream.ReadInteger: Integer;
begin
  Read(Result, sizeof(Result));
end;

function TObjFileStream.ReadJPEGImage(image: TJPEGImage): Integer;
var ms: TMemoryStream;
begin
  ms := TMemoryStream.Create;
  result := ms.CopyFrom(Self, IDSize);
  ms.Seek(0, soFromBeginning);
  image.LoadFromStream(ms);
  ms.Free;
end;

function TObjFileStream.ReadString: String;
var a: array of Char;
    l: Integer;
begin
  SetLength(a, IDSize);
  l := Read(a[0], IDSize);
  SetString(Result, PChar(a), l);
  SetLength(a, 0);
end;

function TObjFileStream.Skip: Integer;
begin
  Seek(IDSize, soFromCurrent);
  Result := IDSize;
end;

function TObjFileStream.WriteBinary(var data; count: Integer): Integer;
var oid: TStreamObj;
begin
  oid := osBinary;
  Write(oid, sizeof(oid));
  Write(count, sizeof(count));
  Write(data, count);
  Result := count;
end;

function TObjFileStream.WriteBMPImage(image: TBitmap): Integer;
var ms: TMemoryStream;
    oid: TStreamObj;
begin
  ms := TMemoryStream.Create;
  image.SaveToStream(ms);
  Result := ms.Size;
  oid := osBMPImage;
  Write(oid, sizeof(oid));
  Write(Result, sizeof(Result));
  CopyFrom(ms, 0);
  ms.Free;
end;

function TObjFileStream.WriteInteger(Value: Integer): Integer;
var oid: TStreamObj;
begin
  oid := osInteger;
  Write(oid, sizeof(oid));
  Result := sizeof(Value);
  Write(Result, sizeof(Result));
  Write(Value, sizeof(Value));
end;

function TObjFileStream.WriteJPEGImage(image: TJPEGImage): Integer;
var ms: TMemoryStream;
    oid: TStreamObj;
begin
  ms := TMemoryStream.Create;
  image.SaveToStream(ms);
  Result := ms.Size;
  oid := osJPEGImage;
  Write(oid, sizeof(oid));
  Write(Result, sizeof(Result));
  CopyFrom(ms, 0);
  ms.Free;
end;

function TObjFileStream.WriteString(s: String): Integer;
var oid: TStreamObj;
begin
  oid := osString;
  Write(oid, sizeof(oid));
  Result := length(s);
  Write(Result, sizeof(Result));
  Write(s[1], Length(s));
end;

end.
0
 
captainklinkAuthor Commented:
Epsylon,

Thanks a lot. Only one problem though, my compiler didn't like the
 
var a: array of Char;

in the ReadString function.
I have delphi3, is there a compiler option or something that I don't have on? When i didn't use the ReadString function, it worked properly.

thanks, CK.
0
 
EpsylonCommented:
I will rewrite that part.

It's a dynamic array, Introduced in Delphi 4.
Sorry for the inconvenience.

Epsylon.
0
 
EpsylonCommented:
Just replace the functions ReadBinary and ReadString. I tested it with Delphi 3.


function TObjFileStream.ReadBinary(var data; count: Integer): Integer;
  function Min(a, b: Integer): Integer;
  begin
    if a < b then Result := a
    else Result := b;
  end;
begin
  Result := Read(data, Min(count, IDSize));
  if Result < IDSize then
    Seek(IDSize - count, soFromCurrent);
end;


function TObjFileStream.ReadString: String;
var a: PChar;
    l: Integer;
begin
  a := AllocMem(IDSize);
  l := Read(a^, IDSize);
  SetString(Result, a, l);
  FreeMem(a);
end;



Cheers,

Epsylon.
0
 
EpsylonCommented:
Any progress?
0
 
captainklinkAuthor Commented:
Epsylon,

Thanks a lot, that's very useful. It's a really useful function. I've added in some things like changing the ObjectStream base class to TMemoryStream instead of TFileStream, that way I can embed an ObjectStream inside of an ObjectStream, VERY useful. I also added a function for saving and loading a stream, that way i can save and load a TTreeView or anything else. do you think it would be useful if I turned this into a component for other people to use? Well, thanks again! Thanks everyone else too for your input!

P.S. how do I go about getting those points to You?
CK
0
All Courses

From novice to tech pro — start learning today.