当我第一次从 TClientDataSet 中读出图片数据时, 发现不是图片!
慢慢观察发现是前面多了 8 个字节(前 4 个字节是 01 00 00 01, 估计是格式标识和头大小; 后 4 个字节是后面图片文件的大小), 去掉这个 8 个字节就是图片文件了.
下面的例子先是检索了 20 个示例文件的所有图片字段, 并把其中的图片提取到指定文件夹;
还把一个指定字段中的图片显示在了窗体上.
//先在窗体上放 ClientDataSet1 和两个 Button
uses IOUtils, Types;
{ 把示例文件中的所有图片提取到 C:\Temp\ }
procedure TForm1.Button1Click(Sender: TObject);
const
DestPath = 'C:\Temp\';
var
PathArr: TStringDynArray;
Dir, Path: string;
Field: TField;
BmpName: string;
begin
{ 获取范例文件列表 }
Dir := GetEnvironmentVariable('CommonProgramFiles') + '\CodeGear Shared\Data\';
PathArr := TDirectory.GetFiles(Dir, '*.cds');
for Path in PathArr do { 分别处理每个文件 }
begin
ClientDataSet1.LoadFromFile(Path);
for Field in ClientDataSet1.Fields do { 遍历每个字段 }
begin
Tag := 0;
if (Field.DataType = ftGraphic) then { 如果是图片字段 }
begin
ClientDataSet1.First;
while not ClientDataSet1.Eof do { 遍历每个记录 }
begin
if not Field.IsNull then { 如果字段不为空 }
begin
{ 确定要保存的目录和文件名 }
BmpName := TPath.GetFileNameWithoutExtension(Path); { 不带后缀的文件名 }
BmpName := Format('%s%s_%.2d.bmp', [DestPath, BmpName, Tag]);
Tag := Tag + 1;
{ 把图片数据提取到流, 删除前 8 个字节后保存 }
with TBytesStream.Create(Field.AsBytes) do
begin
Move(Bytes[8], Bytes[0], Size - 8);
SetSize(Size - 8);
SaveToFile(BmpName);
Free;
end;
end;
ClientDataSet1.Next;
end;
end;
end;
end;
end;
{ 把示范文件 biolife.xml 第一个记录中 Graphic 字段中的图片画在窗体上 }
procedure TForm1.Button2Click(Sender: TObject);
var
Stream: TBytesStream;
Bitmap: TBitmap;
Path: string;
begin
Path := GetEnvironmentVariable('CommonProgramFiles') + '\CodeGear Shared\Data\biolife.xml';
ClientDataSet1.LoadFromFile(Path);
Stream := TBytesStream.Create(ClientDataSet1.FieldByName('Graphic').AsBytes);
Stream.Position := 8;
Bitmap := TBitmap.Create;
Bitmap.LoadFromStream(Stream);
Canvas.Draw(10, 10, Bitmap);
Bitmap.Free;
Stream.Free;
end;
这是提取到的图片: