把几张图片以流的方式存在同一个表字段中,而读取时如何区分它们 ?(流的基本操作)(50分)

  • 主题发起人 主题发起人 Defo_XYF
  • 开始时间 开始时间
D

Defo_XYF

Unregistered / Unconfirmed
GUEST, unregistred user!
如题...........
 
把标识一起存入到相同字段中
 
我这两天也在关注同样的问题.
帮顶.
 
To Easykoala
关键是怎么去区分这些标识呀,给句Code...Thanks!
 
按一下组织就可以了
TPictureInfo= packed record
id: integer;
imagesize: integer;
end;

TPictureInfoArray: array[0..n] of TPictureInfo;
 
楼上,我还是没明白你的意思,我虽然知道每个图片的信息,但是当我存到数据库同一个字段当中之后,怎么读取出指定的图片.
比如: 我有三张图片,A B C 都存在Image字段中,我怎样把B 读出来.
小弟比较愚钝,请说详细点,谢谢!
 
sizeof(TPictureInfo)=8
三张图片 3*8=24 bytes
if Size(A图片)= 2048 bytes
B图片d的起始位置: 24 + 2048
不是吗?
 
自己订个协议就可以了嘛,就是说自己在每张图结束的地方加个标志,读的时候判断一下就可以了
 
都变成流了,唯一方法是按大小取出,不过高难度哦
 
MIME,电子邮件的附件就是用的这种格式,实际上你的应用没有这么复杂,简单的编一个规范就可以了。比如:头两个字节表示有几个图片。每个图片之间用个分隔符,如FFFF什么的,接下来的一个字节表示图片类型,再用两个字节表示这个图片的长度(大小),后面就是图片的长度个字节的实际内容。
 
至于流的基本操作,看看TMemoryStream的帮助就可以了。
 
procedure TForm1.ReadStreamFromField(Field: TField; Stream: TStream;
var Ext: string);
var
MS: TMemoryStream;
Len: Integer;
fbuf: array[0..3] of char;
begin
MS := TMemoryStream.Create;
try
TBlobField(Field).SaveToStream(MS);
Len := 4;
FillChar(fbuf, Len, 0);
MS.Position := soFromBeginning;
MS.ReadBuffer(fbuf, Len);
Ext := fbuf;
Stream.CopyFrom(MS, MS.Size-Len);
finally
MS.Free;
end;
end;

procedure TForm1.WriteStreamToField(Field: TField; Stream: TStream;
const Ext: string);
var
MS: TMemoryStream;
Len: Integer;
fbuf: PChar;
begin
MS := TMemoryStream.Create;
try
Len := 4;
fbuf := PChar(Ext);
MS.WriteBuffer(fbuf^, Len);
MS.CopyFrom(Stream, 0);
TBlobField(Field).LoadFromStream(MS);
finally
MS.Free;
end;
end;
 
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, DB, ADODB, dxmdaset, StdCtrls, jpeg, DBCtrls;

type
TForm1 = class(TForm)
Image1: TImage;
ADOQuery1: TADOQuery;
btnWrite: TButton;
btnRead: TButton;
DataSource1: TDataSource;
procedure btnWriteClick(Sender: TObject);
procedure btnReadClick(Sender: TObject);
procedure Image1DblClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure ReadStreamFromField(Field: TField; Stream: TStream; var Ext: string);
procedure WriteStreamToField(Field: TField; Stream: TStream; const Ext: string);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ReadStreamFromField(Field: TField; Stream: TStream;
var Ext: string);
var
MS: TMemoryStream;
Len: Integer;
fbuf: array[0..3] of char;
begin
MS := TMemoryStream.Create;
try
TBlobField(Field).SaveToStream(MS);
Len := 4;
FillChar(fbuf, Len, 0);
MS.Position := soFromBeginning;
MS.ReadBuffer(fbuf, Len);
Ext := fbuf;
Stream.CopyFrom(MS, MS.Size-Len);
finally
MS.Free;
end;
end;

procedure TForm1.WriteStreamToField(Field: TField; Stream: TStream;
const Ext: string);
var
MS: TMemoryStream;
Len: Integer;
fbuf: PChar;
begin
MS := TMemoryStream.Create;
try
Len := 4;
fbuf := PChar(Ext);
MS.Write(fbuf^, Len);
MS.CopyFrom(Stream, 0);
TBlobField(Field).LoadFromStream(MS);
finally
MS.Free;
end;
end;

procedure TForm1.btnWriteClick(Sender: TObject);
var
MS: TMemoryStream;
Ext: string;
begin
ADOQuery1.Edit;
MS := TMemoryStream.Create;
try
Image1.Picture.Graphic.SaveToStream(MS);
with Image1.Picture do
begin
if Graphic is TMetafile then
Ext := '.wmf'
else if Graphic is TIcon then
Ext := '.ico'
else if Graphic is TBitmap then
Ext := '.bmp'
else if Graphic is TJPEGImage then
Ext := '.jpg';
end;
WriteStreamToField(ADOQuery1.FieldByName('Fcontent'), MS, Ext);
finally
MS.Free;
end;
ADOQuery1.Post;
end;

procedure TForm1.btnReadClick(Sender: TObject);
var
MS: TMemoryStream;
Ext: string;
begin
ADOQuery1.Edit;
MS := TMemoryStream.Create;
try
ReadStreamFromField(ADOQuery1.FieldByName('Fcontent'), MS, Ext);
MS.SaveToFile('c:/test'+Ext);
Image1.Picture.LoadFromFile('c:/test'+Ext);
finally
MS.Free;
end;
ADOQuery1.Post;
end;

procedure TForm1.Image1DblClick(Sender: TObject);
var
Dlg: TOpenDialog;
begin
Dlg := TOpenDialog.Create(nil);
try
if Dlg.Execute then
Image1.Picture.LoadFromFile(Dlg.FileName);
finally
Dlg.Free;
end;
end;

end.
 
To Wij_Wy
你的代码写的到是不错,可是还是针对一张图片的,我想要多个图片的,用你的方法我没能够行同.
求救 SOS
 
写了一个demo比较乱:
思路:首先把n个文件打开,得到每个文件大小,再为一个buffer分配n个文件的内在空间,
最后需要做的是把buffer存到流中,用image读出
欢迎大家交流
TRecJpeg = record
JpegSize: Integer;
JpegHandle: Integer;
JpegFileName: string;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
RecJpeg_1.JpegFileName := 'c:/pic/1.jpg';
Recjpeg_2.JpegFileName := 'c:/pic/2.jpg';
// RecJpeg_1.JpegFileName := 'c:/pic/1.txt';
// RecJpeg_2.JpegFileName := 'c:/pic/2.txt';
end;

procedure TForm2.btnAddClick(Sender: TObject);//增加两个文件到buffer中.
begin
RecJpeg_1.JpegHandle := FileOpen(RecJpeg_1.JpegFileName,fmOpenRead);
RecJpeg_1.JpegSize := FileSeek(RecJpeg_1.JpegHandle,0,2);
FileClose(RecJpeg_1.JpegHandle);

RecJpeg_2.JpegHandle := FileOpen(Recjpeg_2.JpegFileName,fmOpenRead);
RecJpeg_2.JpegSize := FileSeek(RecJpeg_2.JpegHandle,0,2);
FileClose(RecJpeg_2.JpegHandle);
iJpegAllSize := RecJpeg_1.JpegSize + Recjpeg_2.JpegSize;
OutputDebugString(PChar(Format('文件大小:%d',[iJpegAllSize])));
JpegBuffer := PChar(AllocMem(iJpegAllSize+1));


RecJpeg_1.JpegHandle := FileOpen(RecJpeg_1.JpegFileName,fmOpenRead);
FileRead(RecJpeg_1.JpegHandle,JpegBuffer^,RecJpeg_1.JpegSize);
OutputDebugString(JpegBuffer);
Inc(JpegBuffer,Recjpeg_1.JpegSize);
FileClose(RecJpeg_1.JpegHandle);

RecJpeg_2.JpegHandle := FileOpen(RecJpeg_2.JpegFileName,fmOpenRead);
FileRead(RecJpeg_2.JpegHandle,JpegBuffer^,RecJpeg_2.JpegSize);
Inc(JpegBuffer,RecJpeg_2.JpegSize);
FileClose(RecJpeg_2.JpegHandle);
Dec(JpegBuffer,iJpegAllSize);
OutputDebugString(JpegBuffer);
end;
 
To Cnzzlp :
你的代码我看了,可能本人比较笨 没看太明白,只看到写了,那怎么读出来分别放到Image中去显示呀?
你能不能把你的Demo给我发过来一份?
邮箱:xuyanfei5210@163.com
十分感谢!
 
水平有限,欢迎交流.
unit ReadFile;

interface

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

type
TRecJpeg = record
JpegSize: Integer;
JpegHandle: Integer;
JpegFileName: string;
JpegFileStream: TMemoryStream;
JpegFile: TJPEGImage;
end;

TForm2 = class(TForm)
Button1: TButton;
Image1: TImage;
btnShow: TButton;
procedure FormCreate(Sender: TObject);
procedure btnShowClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form2: TForm2;
Buffer,Buffer2: PChar;
iHandle,iSize: Integer;
msFile :TMemoryStream;

RecJpeg_1,RecJpeg_2: TRecJpeg;
iJpegAllSize:Integer;
JpegBuffer: PChar;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
// iHandle := FileOpen('c:/pic/2.txt',fmOpenRead);
(* iHandle := FileOpen('c:/pic/1.jpg',fmOpenRead);
if(iHandle >=0)then
begin
iSize := FileSeek(iHandle,0,2);
Buffer := PChar(AllocMem(iSize+1));
FileClose(iHandle);
end;

// iHandle := FileOpen('c:/pic/2.txt',fmOpenRead);
iHandle := FileOpen('c:/pic/1.jpg',fmOpenRead);
if(iHandle >=0)then
begin
FileRead(iHandle,Buffer^,iSize);
OutputDebugString(Buffer);
FileClose(iHandle);
end;
msFile := TMemoryStream.Create;
msFile.Write(buffer^,iSize);
msFile.Position := 0;
// msFile.Free;
// FreeAndNil(Buffer); *)
RecJpeg_1.JpegHandle := FileOpen(RecJpeg_1.JpegFileName,fmOpenRead);
RecJpeg_1.JpegSize := FileSeek(RecJpeg_1.JpegHandle,0,2);
FileClose(RecJpeg_1.JpegHandle);

RecJpeg_2.JpegHandle := FileOpen(Recjpeg_2.JpegFileName,fmOpenRead);
RecJpeg_2.JpegSize := FileSeek(RecJpeg_2.JpegHandle,0,2);
FileClose(RecJpeg_2.JpegHandle);
iJpegAllSize := RecJpeg_1.JpegSize + Recjpeg_2.JpegSize;
OutputDebugString(PChar(Format('文件大小:%d',[iJpegAllSize])));
JpegBuffer := PChar(AllocMem(iJpegAllSize+1));


RecJpeg_1.JpegHandle := FileOpen(RecJpeg_1.JpegFileName,fmOpenRead);
FileRead(RecJpeg_1.JpegHandle,JpegBuffer^,RecJpeg_1.JpegSize);
OutputDebugString(JpegBuffer);
RecJpeg_1.JpegFileStream := TMemoryStream.Create;
RecJpeg_1.JpegFileStream.Write(JpegBuffer^,RecJpeg_1.JpegSize);
RecJpeg_1.JpegFileStream.Position := 0;
Inc(JpegBuffer,Recjpeg_1.JpegSize);
FileClose(RecJpeg_1.JpegHandle);

RecJpeg_2.JpegHandle := FileOpen(RecJpeg_2.JpegFileName,fmOpenRead);
FileRead(RecJpeg_2.JpegHandle,JpegBuffer^,RecJpeg_2.JpegSize);
RecJpeg_2.JpegFileStream := TMemoryStream.Create;
RecJpeg_2.JpegFileStream.Write(JpegBuffer^,RecJpeg_2.JpegSize);
RecJpeg_2.JpegFileStream.Position := 0;

Inc(JpegBuffer,RecJpeg_2.JpegSize);
FileClose(RecJpeg_2.JpegHandle);
Dec(JpegBuffer,iJpegAllSize);
OutputDebugString(JpegBuffer);


end;

procedure TForm2.btnShowClick(Sender: TObject);
//var
// jpgFile: TJPEGImage;
begin
// jpgfile := TJPEGImage.Create;
// jpgFile.LoadFromStream(msFile);
// image1.Picture.Assign(jpgFile);
RecJpeg_2.JpegFile := TJPEGImage.Create;
RecJpeg_2.JpegFile.LoadFromStream(RecJpeg_2.JpegFileStream);
image1.Picture.Assign(RecJpeg_2.JpegFile);

(* Buffer2 := PChar(AllocMem(msfile.Size+1));
msFile.Read(Buffer2^,msFile.Size);
OutputDebugString(Buffer2); *)
// image1.Picture.LoadFromFile('C:/pic/1.jpg');

// msFile.Free;
// jpgFile.Free;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
RecJpeg_1.JpegFileName := 'c:/pic/1.jpg';
Recjpeg_2.JpegFileName := 'c:/pic/2.jpg';
// RecJpeg_1.JpegFileName := 'c:/pic/1.txt';
// RecJpeg_2.JpegFileName := 'c:/pic/2.txt';
end;

end.
 
建议你使用压缩方式解决此问题,查找有关压缩的源代码。
 
在每个图片文件的数据流前加4个字节保存这个图片数据流的大小,取出时一次性全部取出,再分割就可以了。
 
很简单,在流的最前面加个索引
array [0..x] of longword;
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
926
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部