我的SQL数据库,员工照片表三个字段,一个:照片类型 varchar(10),照片 image,员工ID varchar(10)
保存:
var
  FileName, ls_filehz_name: string;
  StringStream1: TStringStream;
  jpeg1: TJPEGImage;
begin
  if OpenDialog1.FileName <> '' then
  begin
    FileName := OpenDialog1.FileName;
    ClientDataSet1.Close;
    ClientDataSet1.CommandText := 'insert into 员工照片表(照片类型,照片,员工ID) values(:a,:b,:c)';                //取得打开的图象文件的后缀名
    ls_filehz_name := copy(ExtractFileExt(FileName), 2, 3);
    ClientDataSet1.Params.ParamByName('a').AsString := ls_filehz_name;                //当图象文件格式为bmp时
    if ls_filehz_name = 'bmp' then
    begin
      ClientDataSet1.Params.ParamByName('b').Assign(Image1.Picture);
      ClientDataSet1.Params.ParamByName('c').AsString := Frm_main.user_ID;
      ClientDataSet1.Execute;
    end;                //当图象文件格式为jpg时
    if ls_filehz_name = 'jpg' then
    begin
      StringStream1 := TStringStream.Create(' ');
      jpeg1 := TJPEGImage.Create;
      jpeg1.Assign(Image1.Picture);
      jpeg1.SaveToStream(StringStream1);
      ClientDataSet1.Params.ParamByName('pic').AsBlob := StringStream1.DataString;
      ClientDataSet1.Params.ParamByName('c').AsString := Frm_main.user_ID;
      ClientDataSet1.Execute;
      StringStream1.free;
      jpeg1.free;
    end;
  end;
我现在只试一下读BMP,但总是出现 stream read error..这是怎么回事的?
读图片代码:
var
  bs: TMemoryStream;
begin
  with ClientDataSet1 do
  begin
    Close;
    CommandText := 'select * from 员工照片表 where 员工ID='''+frmmain.user_ID+'''';
    Open;
  end;
  bs := TMemoryStream.Create;
  (ClientDataSet1.FieldByName('照片') as TBlobField).SaveToStream(bs);
  bs.position := 0;
  Image1.Picture.Bitmap.LoadFromStream(bs);
  bs.free;
调试到这句:Image1.Picture.Bitmap.LoadFromStream(bs);
就出现错误了,stream read error.
这个问题error我很长时间了,哪位>能说一下?谢谢!

解决方案 »

  1.   

    你用bs.savetofile()->Image1.Picture.Bitmap.LoadFromfile();试试行不行先
      

  2.   

    Image1.Picture.LoadFromStream(bs);  ?
      

  3.   

    在Dephi中使用TStream读写数据的技巧 
      在Dephi中提供了一个抽象的数据类型TStream来支持对流式数据的操作。这些数据通常来自文件、数据库、内存对象、OLE对象等,TStream提供了统一、简洁的方法来进行数据的读写。在通常情况下,我们并不需要直接使用TStream类,对流式数据的读写封装在VCL控件的方法中。但是如果这些方法无法满足我们的要求,就需要自己手动控制数据的读写。 
    一、 TStream的常用的方法和属性:
    1. function Read(var Buffer; Count: Longint): Longint; virtual; abstract 
    2. function Write(const Buffer; Count: Longint): Longint; virtual; abstract; 
    3. function Seek(Offset: Longint; Origin: Word): Longint; virtual; abstract; 
    4. property Position: Longint; 
    5. property Size: Longint 
      Read,Write,Seek都是纯虚函数,提供了数据读写和定位的抽象的方法。Read方法将数据从Stream中读到Buffer缓冲区中,Write则实现相反的操作,返回值表示实际读写数据的大小。Seek提供了在Stream中移动数据指针的方法。参数Origin可以取soFromBeginning,soFromCurrent,soFromEnd三个值,Offset是偏移量,返回值是当前Stream数据指针的位置。 
      Position表示了数据指针在Stream中的位置。这个属性是可读写的,它实际上就是通过调用Seek方法实现的,所以实际使用时使用这个属性更为方便一些。Size属性表示当前Stream的大小,对于不同的Stream,有些时候是只读的。 
    二、 Stream数据的读写。
    1. SaveToStream(Stream: TStream ); //将类中的数据写到Stream的当前位置中 
    2. LoadFromStream(Stream: TStream); //从当前位置读入Stream里的数据实际使用时我们基本上只要使用上面两个函数就可以了。 
    三、 例子
      TStream的继承树图如图1所示(略),实际使用时比较常用的是TFileStream,TMemoryStream,TblobStream,就以这三种流举一例说明具体用法。 
      创建一个窗体Form1,放置三个按钮btnRead,btnInvert,btnSave和一个文件打开对话框OpenDialog1以及数据控件DataSource1,Table1,test. 
      使用Dephi提供的Database Desktop创建一个表test,表里有一个字段域Image,数据库文件名存为test.db。在窗体上放置一个TDatabase控件dbTest,一个TTable控件Table1,一个DataSource控件DataSource1,一个TDBNavigator控件DBNavigator1。将dbTest与刚才Desktop创建的数据库相连,Table1的TableName属性设为test.db,DataSource1的DataSet属性设为Table1,DBNavigator1的DataSource属性设为DataSource1,VisibleButtons属性前四个设为TRUE。此外,将dbtest的Connected设为TRUE,Table1的Active属性设为TRUE,使得数据库一开始就处于打开状态。事件代码编写如下: 
      1. btnRead的Click事件,这里演示了TFileStream的用法。 var
    MS: TFileStream;
    begin
    if OpenDialog1.Execute then
    begin
    MS:=TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
    Image1.Picture.Bitmap.LoadFromStream(MS);
    MS.Free;
    end;
    end;
      2. btnInvert的Click事件,这里演示了TMemoryStream的用法。其中使用了Invert函数,这是一个简单的将图象反色的函数(仅对真彩图象有效),它返回一个指向处理过的图象数据块的指针。 var
    MS: TMemoryStream;
    pImage: pointer;
    begin
    MS:=TMemoryStream.create;
    Image1.Picture.Bitmap.SaveToStream(MS);
    MS.Position:=0;
    pImage:=Invert(MS.Memory, MS.size); 
    //Memory属性是指向实际内存块的指针
    MS.Write(pImage^,MS.size);
    MS.Position:=0; 
    //上一行代码使指针移到了Stream末尾,所以要复位
    Image1.Picture.Bitmap.LoadFromStream(MS);
    FreeMem(pImage); 
    MS.Free;
    end;
      Invert函数如下:function TForm1.Invert(pImage: pointer; size: Integer): pointer;
    var
    pData, pMem: PChar;
    i: Integer;
    begin
    pMem:=AllocMem(size);
    CopyMemory(pMem,pImage,size);
    pData:=pMem+54;
    for i:=0 to size541 do
    begin
    pData^:=Char(not integer(pData^));
    pData:=pData+1;
    end;
    Result:=pMem;
    end;
      3. btnSave的Click事件,这里演示了TMemoryStream的另一种用法,将Stream中的数据写到数据库中去。 var
    MS: TMemoryStream;
    begin
    MS:=TMemoryStream.create;
    Image1.Picture.Bitmap.SaveToStream(MS);
    MS.Position:=0;
    Table1.Append; 
    //在数据库中添加一条记录
    TBlobField(Table1.FieldbyName('image')).LoadFromStream(MS);
    Table1.Post; 
    //将所作的更新写入数据库
    end;
      4. DBNavigator1的Click事件,这里演示了TBlobStream的用法,使用了和写入时不同的方法来读出数据库的图象数据。 var
    MS: TStream;
    begin
    with Table1 do
    MS:=CreateBlobStream(FieldbyName('image'),bmRead);
    Image1.Picture.Bitmap.LoadFromStream(MS);
    MS.Free;
    end;
      现在你已经能够在文件,数据库,内存中任意读写数据流了。试试看吧!
     
      

  4.   

    to :godear() 我用数据流,我是储存到数据库里面去的,然后再读也来~
      

  5.   

    to: yq3woaini(哈哈镜(初级代码工)我的上面说得很清楚,我想知道为什么这样会错,上面错是什么意思?能否具体些?
      

  6.   

    当我用这个Image1.Picture.Graphic.LoadFromStream(TStream(bs));时出现如下错误提示>>>Project ProClient.exe raised exception class EAccessViolation with message 'Access violation at address 004FB288 in module 'ProClient.exe'. Read of address 00000000'. Process stopped. Use Step or Run to continue.
      

  7.   

    //我觉得有两点
    //1.确保你的SQL语句正确,你的SQL语句可能有错,
    //2.确保你的文件格式为BMPvar
      bs: TMemoryStream;
    begin
      with ClientDataSet1 do
      begin
        Close;
        CommandText := 'select * from 员工照片表 where 员工ID='''
          + frmmain.user_ID + ''';
        Open;
      end;
      //当查询没有记录时,则返回
      if ClientDataSet1.RecordCount = 0 then Exit;  bs := TMemoryStream.Create;
      (ClientDataSet1.FieldByName('照片') as TBlobField).SaveToStream(bs);
      bs.position := 0;
      Image1.Picture.Bitmap.LoadFromStream(bs);
      bs.free;
    end;从你的程序来看,你的错误可能是第1点所造成的,也就是说,
    你可能并没有找到任何记录,所以会出现内存错误
      

  8.   

     use delphi to get/set photo
      

  9.   

    to :duanhai(段海) 里面有记录呀, 是不是图片保存时,没有保存到数据库里面??
    但是,我OPEN 后if ClientDataSet1.FieldByName('照片').AsString='' then Exit;发现不为空呀~
    就是里面有值了,但为什么会出错了呢>..>>>是不是没保存完?还是什么?郁闷啦.....
    各位弟兄.帮我出点策略
      

  10.   

    to :vipxch(雨天) U Eglish,very good~~hehe~~~
      

  11.   

    比较比较你的代码,我的程序没问题:(特别注意读取图像的例子)存储图片的代码:
     //存储图片
       MyJPEG := TJPEGImage.Create;
       try
        with MyJPEG do
        begin
          Assign(Image1.Picture.Graphic);
          MS:=TMemoryStream.create;
          SaveToStream(MS);
          MS.Position:=0;
          TBlobField(FieldbyName('图片')).LoadFromStream(MS);
        end;
       finally
        MyJPEG.Free;
       end;
       try
       Post;
       except
       showmessage('数据无法提交');读取图片的代码:
     if ef_adoquery.RecordCount<>0 then
            begin
            try
              tempstream:=TmemoryStream.Create();
              //将图像字段保存到流中
              TBlobField(mainform.ef_ADOQuery.FieldByName('图片')).SaveToStream(tempstream);
              ////给留定位
              tempstream.Position:=0;  
              //省城临时image
              tempjpeg:=TJPEGImage.Create;
              //存留信息
              tempjpeg.LoadFromStream(tempstream);
              //显示图像
              Image1.Picture.Bitmap.Assign(tempjpeg);
            finally
              tempstream.Free;
              tempjpeg.Free;
            end;
            end;
    能解决你的问题吧:)
      

  12.   

    if ls_filehz_name = 'bmp' then
        begin
          //可能問題出在下面的這句
          //樓主先把你的圖形保存到流中,再調入流,來試一下
          ClientDataSet1.Params.ParamByName('b').Assign(Image1.Picture);
          ClientDataSet1.Params.ParamByName('c').AsString := Frm_main.user_ID;
          ClientDataSet1.Execute;
        end;
      

  13.   

    TO : luckyfire(理想) 参照你的代码,问题解决~,非常感谢,本来我用到dbimage的,但涉及到的表,太多,用POST麻烦,所以我就直接insert update了~.这里是否只对JPEG操作?BMP可以否,我再试试看~,