?
Solved

TFiler???

Posted on 1999-07-02
24
Medium Priority
?
204 Views
Last Modified: 2010-05-18
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
0
Comment
Question by:captainklink
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 14
  • 6
  • 2
  • +2
24 Comments
 
LVL 13

Expert Comment

by:Epsylon
ID: 1385747
Delphi provides things like;

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



0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1385748
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
 
LVL 2

Expert Comment

by:333
ID: 1385749
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 13

Expert Comment

by:Epsylon
ID: 1385750
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
 

Author Comment

by:captainklink
ID: 1385751
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
 
LVL 13

Expert Comment

by:Epsylon
ID: 1385752
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
 
LVL 13

Expert Comment

by:Epsylon
ID: 1385753
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
 

Author Comment

by:captainklink
ID: 1385754
epsylon - How do you use Write/ReadComponentRes? I've tried but I can't figure it out.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1385755
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
 

Author Comment

by:captainklink
ID: 1385756
thanks alot epsylon
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1385757
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
 
LVL 2

Expert Comment

by:333
ID: 1385758
"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
 

Author Comment

by:captainklink
ID: 1385759
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
 
LVL 10

Expert Comment

by:Jacco
ID: 1385760
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
 
LVL 13

Expert Comment

by:Epsylon
ID: 1385761
Hi, I am making progress and I think it will be finished by tomorrow.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1385762
Sorry for the delay but here it is:
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1385763
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
 
LVL 13

Expert Comment

by:Epsylon
ID: 1385764
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
 

Author Comment

by:captainklink
ID: 1385765
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
 
LVL 13

Expert Comment

by:Epsylon
ID: 1385766
I will rewrite that part.

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

Epsylon.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1385767
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
 
LVL 13

Expert Comment

by:Epsylon
ID: 1385768
Any progress?
0
 

Author Comment

by:captainklink
ID: 1385769
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
 
LVL 13

Accepted Solution

by:
Epsylon earned 400 total points
ID: 1385770
Glad you like it!

Now you can grade me  :o)
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses

719 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question