首页 > 数据库 >delphi 初识内存流: 从设置用户头像到从数据库存取图片到的过程

delphi 初识内存流: 从设置用户头像到从数据库存取图片到的过程

时间:2023-05-09 18:36:34浏览次数:61  
标签:begin end Sender FireDAC delphi FMemoryStream 初识 内存

所谓"流", 就是一段数据或是一块内存;
在进行流操作时, 我们不必关心流中的数据到底是什么; 只需要知道流的大小和当前的指针位置. 所以流只有两个属性: 
Size、Position.
对流的操作, 不过就是读取和写入. 所以流最主要的方法就是 Read 和 Write.
在很多控件的使用中, 读取主要用 LoadFromStream; 写入主要用 SaveToStream. 

TStream 是一个抽象的基类, 不能直接生成对象. 在具体的应用中, 主要使用它的子孙类:
TFileStream: 文件流
TStringStream: 字符串流
TMemoryStream: 内存流
TResourceStream: 资源文件流
THandleStream: 是 TFileStream 的父类、TStream 的子类
TCustomMemoryStream: 是 TMemoryStream 和 TResourceStream 的父类、TStream 的子类
与流相关的常用类还有: TReader、TWriter、TCompressionStream、TDecompressionStream

 

Delphi 中的内存流(TMemoryStream)是一种特殊的流对象,它继承自 TCustomMemoryStream 类,可以将数据存储在内存中,而不是存储在文件或其他外部介质中。 内存流有以下特点:

  1. 可以通过向内存流写入数据来将数据保存到内存中;
  2. 可以从内存流中读取数据,并在需要时将其转换为其他数据类型;
  3. 内存流可以任意调整其大小,以容纳更多或更少的数据;
  4. 内存流可以在不使用额外存储空间的情况下随时进行扩展或缩小;
  5. 内存流可以用于在内存中缓存数据,以提高程序的性能。 使用内存流可以方便地将数据存储在内存中

TMemoryStream 的一些常用方法和属性如下:

  1. LoadFromFile 和 SaveToFile:从文件中加载数据或将数据保存到文件中。(常用)
  2. Read 和 Write:从流中读取数据或将数据写入流中。这些方法的参数是一个指针和一个长度。在使用这些方法之前,需要先使用 SetSize 方法设置流的大小。
  3. Seek:定位流中的位置。可以使用这个方法在流中移动指针,以便读取和写入数据。
  4. Size:获取流的大小。
  5. Capacity:获取或设置流的容量。容量是指流的最大大小,如果需要向流中写入更多的数据,可以使用 SetCapacity 方法来增加容量。
  6. Memory 和 MemorySize:获取流中数据的指针和数据的长度。

 一个简单示例:

var
  Stream: TMemoryStream;
  Data: array[0..255] of Byte;
begin
  Stream := TMemoryStream.Create;
  try
    // 写入数据
    Stream.Write(Data, SizeOf(Data));
    // 移动指针到开头
    Stream.Seek(0, soBeginning);
    // 读取数据
    Stream.Read(Data, SizeOf(Data));
  finally
    Stream.Free;
  end;
end;

需要注意的是,在使用 TMemoryStream 时,需要注意内存的使用情况,使用结束后要手动 free,避免出现内存泄漏等问题。同时,在写入和读取数据时,也要注意数据类型的匹配,避免出现类型转换错误等问题。

系统学习'流' ,请转到万一老师的博客:https://www.cnblogs.com/del/archive/2008/01/01/1022124.html

任务需求:

1.从数据库取回图像,并设置到控件上

2.上传图像到数据库

3.用户选择本地图片,进行头像预览(这个反而不是很重要)

数据库设计:

 

界面设计图:

 

 

 OpenPictureDialog1控件filter设置为: 全部 (*.png;*.jpg;*.jpeg)|*.png;*.jpg;*.jpeg  只允许用户选择两种图片类型. 其它控件设置就不展开了.

效果展示:

以下是主要代码

 private
    FMemoryStream: TMemoryStream;

 

第一个问题.把图像从数据库上取回到图片控件

procedure TForm1.GetImgClick(Sender: TObject);
begin
  with FDQUsers do
  begin
    Close;
    sql.Text := 'SELECT * FROM users where userid= 1';
    open;
    //ShowMessage(BoolToStr(IsEmpty, true));  //判断查询是否返回空集
    if not TBlobField(FieldByName('HeadImg')).IsNull then   //判断用户是否有设置头像
    begin
      FMemoryStream.Clear;  //先清除内存流空间
      TBlobField(FieldByName('HeadImg')).SaveToStream(FMemoryStream);    //把图像从数据库载入内存流
      FMemoryStream.Position := 0; //读取位置设置为0
      HeadImg.Picture.LoadFromStream(FMemoryStream);//显示到图片控件上
      labInfo.Caption := '头像已取回';
    end
    else
      labInfo.Caption := '无图片';
  end;
end;

第二个问题,把图像上传到数据库

procedure TForm1.UpdateImgClick(Sender: TObject);   //上传头像到数据库
begin
  with FDQUsers do
  begin
    close;
    sql.Text := 'Update users set headimg=:headimg where userid=1'; //:headimg是占位符
    ParamByName('headimg').LoadFromStream(FMemoryStream, ftBlob); // 填充:headimg占位符,从内存流中上传
    ExecSQL;
    labInfo.Caption := '头像已更新到数据库'
  end;
end;

第三个问题:

procedure TForm1.SetImgClick(Sender: TObject);   //设置头像
var
  FileName: string;
begin
  if OpenPictureDialog1.Execute then
  begin
    FileName := OpenPictureDialog1.FileName;
    HeadImg.Picture.LoadFromFile(FileName);

    FMemoryStream.Clear;
    FMemoryStream.LoadFromFile(FileName); //把本地图片存到内存流中
    FMemoryStream.Position := 0;
    labInfo.Caption := '头像已从本地设置'
  end;
end;

 

 

 

 

以下是全部代码:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf,
  FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async,
  FireDAC.Phys, FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteDef,
  FireDAC.Stan.ExprFuncs, FireDAC.VCLUI.Wait, FireDAC.Stan.Param, FireDAC.DatS,
  FireDAC.DApt.Intf, FireDAC.DApt, FireDAC.Phys.SQLiteWrapper.Stat, Vcl.ExtDlgs,
  Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client, scGPFontControls,
  scControls, scGPControls, scGPImages, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    UserInfoPanel: TscGPPanel;
    HeadImg: TscGPImage;
    UwerNamePnl: TscGPLabel;
    GetImg: TscGPButton;
    UpdateImg: TscGPButton;
    SetImg: TscGPButton;
    AppBar: TscGPPanel;
    btnClose: TscGPCharGlyphButton;
    LabTitle: TscGPLabel;
    P_ErrInfo: TscGPPanel;
    labInfo: TscGPLabel;
    scGPImage1: TscGPImage;
    scGPButton2: TscGPButton;
    FDConnection1: TFDConnection;
    FDQUsers: TFDQuery;
    FDQUsersUserID: TFDAutoIncField;
    FDQUsersUserName: TWideMemoField;
    FDQUsersPassword: TWideMemoField;
    FDQUsersGroupID: TIntegerField;
    FDQUsersIsDisabled: TIntegerField;
    FDQUsersLoginTime: TWideMemoField;
    FDQUsersMAC: TWideMemoField;
    FDQUsersLockTime: TIntegerField;
    DSUsers: TDataSource;
    FDPhysSQLiteDriverLink1: TFDPhysSQLiteDriverLink;
    OpenPictureDialog1: TOpenPictureDialog;
    FDQUsersHeadImg: TBlobField;
    procedure btnCloseClick(Sender: TObject);
    procedure GetImgClick(Sender: TObject);
    procedure UpdateImgClick(Sender: TObject);
    procedure SetImgClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    FMemoryStream: TMemoryStream;
  public
    { Public declarations }

  end;

var
  Form1: TForm1;

implementation
{$R *.dfm}

procedure TForm1.btnCloseClick(Sender: TObject);
begin
  FMemoryStream.Free;
  Close;
end;

procedure TForm1.GetImgClick(Sender: TObject);
begin
  with FDQUsers do
  begin
    Close;
    sql.Text := 'SELECT * FROM users where userid= 1';
    open;
    //ShowMessage(BoolToStr(IsEmpty, true));  //判断查询是否返回空集
    if not TBlobField(FieldByName('HeadImg')).IsNull then   //判断用户是否有设置头像
    begin
      FMemoryStream.Clear;  //先清除内存流空间
      TBlobField(FieldByName('HeadImg')).SaveToStream(FMemoryStream);    //把图像从数据库载入内存流
      FMemoryStream.Position := 0; //读取位置设置为0
      HeadImg.Picture.LoadFromStream(FMemoryStream); //显示到图片控件上
      labInfo.Caption := '头像已取回';
    end
    else
      labInfo.Caption := '无图片';
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FMemoryStream := TMemoryStream.Create;
end;

procedure TForm1.SetImgClick(Sender: TObject);   //设置头像
var
  FileName: string;
begin
  if OpenPictureDialog1.Execute then
  begin
    FileName := OpenPictureDialog1.FileName;
    HeadImg.Picture.LoadFromFile(FileName);

    FMemoryStream.Clear;
    FMemoryStream.LoadFromFile(FileName); //把本地图片存到内存流中
    FMemoryStream.Position := 0;
    labInfo.Caption := '头像已从本地设置'
  end;
end;

procedure TForm1.UpdateImgClick(Sender: TObject);   //上传头像到数据库
begin
  with FDQUsers do
  begin
    close;
    sql.Text := 'Update users set headimg=:headimg where userid=1'; //:headimg是占位符
    ParamByName('headimg').LoadFromStream(FMemoryStream, ftBlob); // 填充:headimg占位符,从内存流中上传
    ExecSQL;
    labInfo.Caption := '头像已更新到数据库'
  end;
end;

end.

 

标签:begin,end,Sender,FireDAC,delphi,FMemoryStream,初识,内存
From: https://www.cnblogs.com/yoooos/p/17384511.html

相关文章

  • 解析内存中的高性能图结构
    在进行各种图处理、图计算、图查询的时候,内存或是硬盘中如何存储图结构是一个影响性能的关键因素。本文主要分析了几种常见的内存图结构,及其时间、空间复杂度,希望对你有所启发。通常来说,对于图结构的几种常见的基础操作:插入一个点插入一个边删除一个边删除一个点的全部邻边......
  • CTF-MISC-内存取证(持续更新)
    1.恶意程序注册表题目来源-2021强网杯 附件为未知文件,用010editor查看  7z文件,修改后缀名 解压出一个镜像文件非预期解:根据题目提示,可以搜索注册表申请命令REGQUERY命令,用010editor查看 可以得到答案正确解法可查看这个大佬(30条消息)第五届强网杯全国网络......
  • delphi cannot make a visible window modal报错的解决过程
    抛出问题: 排除过程:1.在TFrmChangePW窗口的create事件里打断点,结果发现,根本没停顿,所以判断问题不在TFrmChangePW窗体里,而是showmodal这语句里出了问题,点中断,跳到抛出错误的地方:2.if里的四个条件,检查了第一个,第二个和第四个都是没问题的,第三个(fsModalinFFormS......
  • CUDA 内存处理
    第六章CUDA内存处理6.1高速缓存G80与GT200系列没有与CPU中高速缓存等价的存储器。在Fermi架构的GPU实现中,第一次引入了不基于程序员托管的数据缓存这个概念。这个架构的GPU中每个SM有一个一级缓存,这个一级缓存既是基于程序员托管的又是基于硬件托管的。在所有的SM之间有一......
  • opencv图片内存占用过大优化
    //读取图片文件到内存std::ifstreamfile(img.toStdString(),std::ios::binary);std::vector<char>buffer((std::istreambuf_iterator<char>(file)),std::istreambuf_iterator<char>());cv::Matimage=cv::imdecode(cv::Ma......
  • 【内存分析】用于内存分析定位的指令 jmap, jstat, jinfo, jstack
    用于内存分析定位的指令/工具有:jmap,jstat,jinfo,jstackjmap(1)分析进程中的内存使用情况,是多少个什么样的对象占用了多大的内存,这类型的分析(2)也可以导出堆转储文件,导出后,再来分析jstack这个是看cpu的,看各个线程的执行状态,如果cpu比较高,就是用jstack来定位分析......
  • IBM Power 内存缺失问题
     转自:http://blog.chinaunix.net/uid-22759617-id-3456302.html IBMP5小型机内存缺失问题处理方法总结p55A机器有2G的内存无法检测出来。机器型号:9133-55A<1>联系前方找一根网线,一头连接55A小型机后端的HMC1口,一头连接电脑的网口。<2>提示前方打开IE,在IE地址栏输入后回车,......
  • 全新 – Amazon EC2 R6a 实例由第三代 AMD EPYC 处理器提供支持,适用于内存密集型工作
    我们在Amazonre:Invent2021上推出了通用型AmazonEC2 M6a实例,并于今年2月推出了计算密集型 C6a实例。这些实例由运行频率高达3.6GHz的第三代AMDEPYC处理器提供支持,与上一代实例相比,性价比提高多达35%。如今,我们正在扩展产品组合,添加内存优化型 AmazonEC2R6a......
  • ibm power 内存条 顺序 P740 P720 740
            https://www.renrendoc.com/paper/175507929.html......
  • Delphi工具开发的windows应用程序,自动化测试工具
    DUnit:DUnit是一种单元测试框架,可以帮助开发人员编写单元测试用例,测试Delphi应用程序的各个模块和组件。TestComplete:一个功能强大的自动化测试工具。可以对Delphi应用程序进行测试,支持多种脚本语言和测试框架,如JScript、VBScript、Python、JUnit等DelphiAutomatedTestingSui......