如何把文件以流的形式写入数据库?数据库的字段类型应该是什么?还有就是如何把数据库的数据恢复为文件?各位大哥帮帮忙,无限感激!最好能给些代码。

解决方案 »

  1.   

    以下是一个用流保存与读取RichEdit的示例,你可以改一下,其实都是差不多的:
    存:
    var
      MemStrm:TMemoryStream;
    begin
      MemStrm:=TMemoryStream.Create;
      try
        RichEdit1.Lines.SaveToStream(MemStrm);
        Table1.Edit;
        TBlobField(Table1.FieldByName('RichEdit')).LoadFromStream(MemStrm);
        Table1.Post;
      finally
        MemStrm.Free;
      end;end;
    取:
    var
      MemStrm:TMemoryStream;
    begin
      MemStrm:=TMemoryStream.Create;
      try
        TBlobField(Table1.FieldByName('RichEdit')).SaveToStream(MemStrm);
       RichEdit1.Lines.LoadFromStream(MemStrm);
      finally
        MemStrm.Free;
      end;
    end;
      

  2.   

    楼上说的对,或者用TBlobStream对象来实现,方法和上面差不多的,请查看帮助
      

  3.   

    TMemoryStream的继承关系如下
    TObject
    |
    TStream
    |
    TCustomMemoryStream
    |
    TMemoryStream
    如何使用TMemoryStream?
    其实TmemoryStream使用就跟TStream 一样
    具体的属性,方法可看帮助。
    下举一例:
    如我想在内存中直接读写一个Bitmap,怎么办?
    TmemoryStream帮了你大忙var
      BitmapMemoryStream:TMemoryStream;
      Bitmap1:TBitmap;procedure TForm.Button1Click(Sender:TObject);
    begin
        BitmapmemroyStream:=TmemoryStream.Create; file://建立MemoryStream
        Bitmap1:=TBitmap.Create;
        try
          Bitmap1.LoadFromFile(’d:\Bitmap1.bmp’);
        except
             ShowMessage(’Error On LoadFile bitmap1.bmp’);
    end;
    end;procedure TForm.Button2Click(Sneder:Tobject);
    begin
      if Assigned(Bitmap1) then
      Bitmap1.SaveToStream(BitmapmemoryStream);
    end;procedure TForm.Button3Click(Sender:TObject);
    begin
      if BitmapMemoryStream<>nil then
       begin
         try
            BitmapMemroyStream.SaveToFile(’Bitmap1.str’); file://内存流保存,大小与
                                                           file://Bitmap1.bmp一样
         except
           showmessage(’error on access memory!’);
        end;
      end;
    end;procedure TForm.Button4Click(Sender:TObject);
    var
       Buffer:Array[0..53] of char;
    begin
       if Assigned( BitmapMemroyStream) then
    try
       BitmapMemroyStream.Seek(0,soFromBeginning);
       BitmapMemoryStream.Read(Buffer,54);
       if Buffer[0]=’B’ and Buffer[1]=’M’ then file://改写内存内容
           begin
             BitmapMemoryStream.Seek(0,soFromBeginning);
             BitmapmemoryStream.Write(’ICE’,3);
             Button3Click(Sender);//将改写的内容写入文件
       end;
    except
        ShowMessage(’error On Access memroyStream’);
    end;
    end;大家可看到用TMemoryStream对与内存读写多么方便,当然其实用不着先建一Bitmap
    可以用LoadFromFile直接引导文件,但是如果对于其它的内存流却是可以用上述方法
    上文只是抛转引玉,其它的一些功能大家可以看帮助,自己琢磨!
    还有很多其它的流式对象,大致都差不多,一通百通!
    如何将一个流的内容写入到剪贴板中,并处理这个技巧是参考Delphi的剪贴板类的实现来完成的。将一个流的内容放入剪贴板,
    首先要注册你自已的格式,使用RegisterClipboardFormat()函数
    然后做下面三步:
    1.创建一个内容流,并将内容写进去
    2.创建一个全局的内容区,并将流的内容写入
    3.调用ClipBoard.SetAsHandle()将内容写入剪贴板
    将内容写入剪贴板中
    var
    hbuf : THandle;
    bufptr : Pointer;
    mstream : TMemoryStream;
    begin
    mstream := TMemoryStream.Create;
    try
    {-- 处理流的代码 --}
    hbuf := GlobalAlloc(GMEM_MOVEABLE, mstream.size);
    try
    bufptr := GlobalLock(hbuf);
    try
    Move(mstream.Memory^, bufptr^, mstream.size);
    Clipboard.SetAsHandle(CF_MYFORMAT, hbuf);
    finally
    GlobalUnlock(hbuf);
    end;
    except
    GlobalFree(hbuf);
    raise;
    end;
    finally
    mstream.Free;
    end;
    end;
    请注意不要将分配的全局缓冲区释放,这个工作由剪贴板来完成,在读出数据中
    你应该将它复制后处理。将剪贴板内容读出来
    var
    hbuf : THandle;
    bufptr : Pointer;
    mstream : TMemoryStream;
    begin
    hbuf := Clipboard.GetAsHandle(CF_MYFORMAT);
    if hbuf <> 0 then begin
    bufptr := GlobalLock(hbuf);
    if bufptr <> nil then begin
    try
    mstream := TMemoryStream.Create;
    try
    mstream.WriteBuffer(bufptr^, GlobalSize(hbuf));
    mstream.Position := 0;
    {-- 处理流的代码 --}
    finally
    mstream.Free;
    end;
    finally
    GlobalUnlock(hbuf);
    end;
    end;
    end;
    end;
    在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 ); file://将类中的数据写到Stream的当前位置中
    ---- 2. LoadFromStream(Stream: TStream); file://从当前位置读入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); file://Memory属性是指向实际内存块的指针
       MS.Write(pImage^,MS.size);
       MS.Position:=0; file://上一行代码使指针移到了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 Size-54-1 do
        begin
          pData^:=Char(not integer(pData^));//地址取反
          pData:=pData+1;
       end;
      Result:=pMem;
    end;---- 1. btnSave的Click事件,这里演示了TMemoryStream的另一种用法,
    将Stream中的数据写到数据库中去。
    var
      MS: TMemoryStream;
    begin
      MS:=TMemoryStream.create;
      Image1.Picture.Bitmap.SaveToStream(MS);
      MS.Position:=0;
      Table1.Append; file://在数据库中添加一条记录
      TBlobField(Table1.FieldbyName('image')).LoadFromStream(MS);
      Table1.Post;
      file://将所作的更新写入数据库
    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.   

    非常感谢  xzhifei(飞) 、 snake_eye(天使的披风) 的提示。问题已经解决。为了共同学习,我把我的方法也说一说,虽然这是一个很菜鸟的问题。我要打开不同格式的多种文件,比如,图片、word文档、Excel文档还有其它
    并且要把这些不同的文档在同一个窗口里打开,并一起存入数据库。我首先说说我的打开方式:
    在这里我用了ActiveX控件RichTextBox,并通过OLE.
    procedure TfrmContractOther.cmdInsertClick(Sender: TObject);
    var
        nCount:Integer;
        sname:string;
        strFileName:String;
    begin
        nCount := RichTextBox1.OLEObjects.Count;
        sname := 'f'+inttostr(nCount);
        if OpenDialog1.Execute() then
        begin
            strFileName := OpenDialog1.FileName;
            RichTextBox1.OLEObjects.Add(nCount, sname ,strFileName,0);
        end;
    end;把不同的文档在RichTextBox1中打开后,接下来的问题就是如何来存入数据库了。
    导入数据库的方法可以用流的形式来实现,但是RichTextBox1支持savefile()
    和loadfile()方法,所以实现起来就简单得多了。
    实现方法:
     1、保存:先将RichTextBox中的对象保存为文件——>将文件保存到数据库——>删除文件
     2、打开:将数据库中的对象还原到一个文件对象中——>RichTextBox装入文件
    以上是我的做法,问题很简单耽误大家时间了。
    很希望大家在解决一个问题的时候,能够说说自己的心得。谢谢楼上的三位大哥。