• ADO.NET笔记——读取二进制大对象(BLOB)


    相关知识:

    1. 在SQL Server中,一般情况下,每行数据的总长度不能超过8K字节。因此,下列数据类型的长度,也不能超过8K字节:binary,char(),nchar(),varchar(),nvarchar()。注意,由于nvarchar是Unicode字符,因此,其最大长度也不能超过nvarchar(4000)
    2. 对于超长数据,尤其是二进制数据(例如音频视频数据等),SQL Server提供了下列数据类型(可以超过8K):image,varbinary(max),text,ntext,varchar(max),nvarchar(max)
    3. 对于较小的二进制数据,可以公国DataReader或者DataSet一次性读取。但是对于较大的二进制数据(BLOB),例如1MB以上,如果一次性把所有数据都读取出来,就会消耗大量的程序内存(字节数组)。因此,往往是采用分批读取的方式进行
    4. SqlDataReader的二进制读取:
      • 在ExecuteReader调用时,要指定CommandBehavior.SequentialAccess选项,以表明通过顺序的方式逐段读取
         SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
      • GetBytes函数,可以将二进制字段中的数据逐段读到缓冲区中
      • 应当优先把BLOB字段前的其他字段读取出来,否则一旦开始读BLOB字段,将无法再回头去读之前的字段

    代码示例:

    • 数据库:采用红皮书的示例数据库,AdventureWorks_WroxSSRS2012,使用Production.ProductPhoto表,获取其中的图片数据信息

       

    • 引入:
      using System.Data;
      using System.Data.SqlClient;
      using System.IO;
    • 基本定义:
      1         const int BUF_SIZE = 1024;//缓冲区大小
      2         static string strConn = @"server=Joe-PC;database=AdventureWorks_WroxSSRS2012;uid=sa;pwd=root";
      3         static SqlConnection conn = new SqlConnection(strConn);
      4         //优先把BLOB字段前的其他字段读取出来,否则一旦开始读BLOB字段,将无法再回头去读之前的字段(注意此sql语句中字段的顺序与数据库字段顺序的对比)
      5         static string strCmd = "SELECT ProductPhotoID,ThumbnailPhotoFileName,ThumbNailPhoto,LargePhotoFileName,LargePhoto FROM Production.ProductPhoto";
      6         static SqlCommand cmd = new SqlCommand(strCmd, conn);
    • 访问ProductPhoto表
       1         static void Main(string[] args)
       2         {
       3             try
       4             {
       5                 conn.Open();
       6                 //以SequentialAccesss方式打开DataReader
       7                 SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
       8                 while (dr.Read())
       9                 {
      10                     int productPhotoID = dr.GetInt32(0);
      11                     string thumbnailPhotoFileName = dr.GetString(1);//读取缩略图文件名
      12                     WriteThumbnailPhotoFile(thumbnailPhotoFileName, dr);//将缩略图二进制数据写入磁盘文件
      13                     string largePhotoFileName = dr.GetString(3);//读取大图文件名
      14                     WriteLargePhotoFile(largePhotoFileName, dr);//将大图二进制数据写入磁盘文件
      15                 }
      16             }
      17             catch (Exception e)
      18             {
      19                 Console.WriteLine(e);
      20             }
      21             finally
      22             {
      23                 conn.Close();
      24             }
      25         }
    • 将缩略图二进制数据写入磁盘文件的函数
      1         static void WriteThumbnailPhotoFile(string fileName, SqlDataReader dr)
      2         {
      3             string path = "..\..\images\Thumbnail\" + fileName;//需要预先在项目文件夹中建立此目录
      4             FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write);
      5             //ThumbnailPhoto的数据比较小(没有超过8KB),因此选择一次性读出,直接写入文件
      6             byte[] buf = dr[2] as byte[];
      7             fs.Write(buf, 0, buf.Length);
      8             fs.Close();
      9         }
    • 将大图二进制数据写入磁盘文件的函数
       1         static void WriteLargePhotoFile(string fileName, SqlDataReader dr)
       2         {
       3             string path = "..\..\images\Large\" + fileName;//需要预先在项目文件夹中建立此目录
       4             FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write);
       5             byte[] buf = new byte[BUF_SIZE];
       6             long bytesRead = 0;
       7             long startIndex = 0;
       8             //LargePhoto的数据比较大,因此分批次读出,分别写入文件
       9             while ((bytesRead = dr.GetBytes(4, startIndex, buf, 0, BUF_SIZE)) > 0)
      10             {
      11                 fs.Write(buf, 0, (int)bytesRead);
      12                 startIndex += bytesRead;
      13             }
      14             fs.Close();
      15         }

    程序说明:

    需要预先在本项目文件夹下建立images目录,内有thumbnail和large子目录,用于存放从数据库获取的图片

  • 相关阅读:
    1.5 判断是奇数还是偶数(比较运算符 & if...else)
    1.4计算器 (数字类型 & 算术运算符 &赋值运算符)
    1.3hello 张三(终端交互 & 字符串)
    1.2python语言环境 & python IDE(集成开发环境)搭建
    Centos 7 下安装jdk 7
    Centos 7 安装redis
    git 学习笔记
    git 基础操作
    git 获取远程分支的代码
    redis基础操作
  • 原文地址:https://www.cnblogs.com/chenguangqiao/p/4357238.html
Copyright © 2020-2023  润新知