我有一个图像,一个字符串和一个整数,我需要保存/读取为文件。什么是最好的方法来做到这一点。我在考虑一个TStream,但我不确定如何实现它。
答案 0 :(得分:3)
虽然您可以使用自己的容器格式,但使用预先存在的容器格式对我来说更有意义。
对我来说最明显的选择是ZIP文件。 Delphi内置了库来读写ZIP文件。这就是Office保存文件的方式。就像Office一样,您不需要使用.zip扩展名。
您可以将图像放在ZIP中的一个文件中,将元数据放在另一个文件中。例如,元数据可以作为JSON持久化。
答案 1 :(得分:3)
您可以使用Delphi的内置组件流支持,并将其保存为二进制或文本数据。这种方法的一个缺点是,如果您的图像是高分辨率的,那么与图像的原始文件格式相比,当将内存像素数据转储到磁盘时,您可能会受到更大文件大小的惩罚。 JPEG。在下面的示例中,我从TImage
派生了一个类,并添加了一个字符串值MyString
和一个整数MyInteger
并保存为二进制数据。
将组件流式传输到二进制文件
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;
type
TMyImage = class(TImage)
private
FString : string;
FInteger : integer;
public
published
property MyString: string read FString write FString;
property MyInteger: Integer read FInteger write FInteger;
end;
TFormMain = class(TForm)
procedure FormCreate(Sender: TObject);
private
FMyImage : TMyImage;
FMyImage2 : TMyImage;
public
end;
var
FormMain: TFormMain;
implementation
{$R *.dfm}
procedure WriteComponent(Component: TComponent; Filename : String);
var
m :TMemoryStream;
begin
m := TMemoryStream.Create;
try
m.WriteComponent(Component);
m.Seek(0, soFromBeginning);
m.SaveToFile(Filename);
finally
m.Free;
end;
end;
function ReadComponent(Filename : String): TComponent;
var
m :TMemoryStream;
begin
m := TMemoryStream.Create;
try
m.LoadFromFile(FileName);
m.Seek(0, soFromBeginning);
result := m.ReadComponent(nil);
finally
m.Free;
end;
end;
procedure TFormMain.FormCreate(Sender: TObject);
begin
FMyImage := TMyImage.Create(Self);
FMyImage.Picture.LoadFromFile('C:\...\Delphi\Common Images\ALIGNPAL.BMP');
FMyImage.MyString := 'Hello World';
FMyImage.MyInteger := 12345;
WriteComponent(FMyImage, 'c:\test.dat');
FMyImage2 := ReadComponent('c:\test.dat') as TMyImage;
end;
initialization
RegisterClass(TMyImage);
end.
简化方法
如果你只想使用一个字符串和一个整数,那么你可以使用TImage的字幕和标签属性。
...
FImage : TImage;
FImage2 : TImage;
....
procedure TFormMain.FormCreate(Sender: TObject);
begin
FImage := TImage.Create(Self);
FImage.Picture.LoadFromFile('C:\...\Delphi\Common Images\ALIGNPAL.BMP');
FImage.Caption := 'Hello World';
FImage.Tag := 12345;
WriteComponent(FImage, 'c:\test.dat');
FImage2 := ReadComponent('c:\test.dat') as TImage;
end;
将组件流式传输到文本
如果你想通过对二进制数据进行字符串表示来获得更多“可读”的数据文件,下面我还添加了有用的辅助函数found here。但文件大小会增加。
function StringToComponentProc(Value: string): TComponent;
var
StrStream:TStringStream;
BinStream: TMemoryStream;
begin
StrStream := TStringStream.Create(Value);
try
BinStream := TMemoryStream.Create;
try
ObjectTextToBinary(StrStream, BinStream);
BinStream.Seek(0, soFromBeginning);
Result:= BinStream.ReadComponent(nil);
finally
BinStream.Free;
end;
finally
StrStream.Free;
end;
end;
function ComponentToStringProc(Component: TComponent): string;
var
BinStream:TMemoryStream;
StrStream: TStringStream;
s: string;
begin
BinStream := TMemoryStream.Create;
try
StrStream := TStringStream.Create(s);
try
BinStream.WriteComponent(Component);
BinStream.Seek(0, soFromBeginning);
ObjectBinaryToText(BinStream, StrStream);
StrStream.Seek(0, soFromBeginning);
Result:= StrStream.DataString;
finally
StrStream.Free;
end;
finally
BinStream.Free
end;
end;
答案 2 :(得分:1)
在this SO问题中讨论了向图像添加任意数据而不影响可用性的一些有趣的方法。