2

我需要将二进制文件(zip 文件)转换为十六进制表示,然后将其作为 varbinary(max) 函数参数发送到 sql-server。

一个完整的例子(使用一个非常小的文件!)是:

1)我的文件包含以下位0000111100001111

2)我需要一个程序来快速将其转换为0F0F

3)我将调用一个0x0F0F作为参数传递的sql server函数

问题是我有大文件(最大 100MB,即使平均文件大小为 100KB 文件也是可能的),所以我需要最快的方法来做到这一点。

否则说明:我需要创建字符串

'0x'+BinaryDataInHexadecimalRepresentation

以最有效的方式。(注意:可能有一种方法可以立即打开文件并获取十六进制字符串,所以在这种情况下,我只需要使用“这种方式”,如果有的话)。

相关问题:将十六进制数据传递给 sql server

更新:阅读评论后,我认为需要在此处添加更多信息。我尝试使用 T-SQL 文本命令将二进制数据发送到存储过程的原因是,通过这种方式我消除了服务器的一些开销:存储过程接收二进制数据并将其写入文件(这是我的最终目标)。如果我使用 DAC 组件,我将能够轻松地将 biray 数据发送到服务器,但在这种情况下,我需要使用临时表来存储数据,然后将此数据发送到写入文件的存储过程。

所以这个想法是:

1)使用T-SQL“long”命令:客户端开销更大,因为我需要读取文件并将其转换为十六进制以准备长命令;更少的服务器开销,因为 sql server 只接收二进制数据并在存储函数中处理它

2)使用DAC:我需要通过sql server中的临时表,因此在服务器上有更多开销

由于我将服务器用作 Web 文档服务器(这是一个技巧),我想尝试减少服务器上的开销。无论如何可能是我错了,(2)无论如何是比(1)更好的技术

4

1 回答 1

1

好吧,这是一个选项,可以尽可能快地进行转换。

代码特点:

  • 字符串只有一个分配(所以没有重新分配,也没有移动或复制)
  • 从文件中快速读取。

因为我们知道一个字节正好转换为两个十六进制字符,所以我们知道我们的结果字符串需要正好是文件大小的两倍。我们分配一个所需大小的字符串,然后以足够大的块从文件中读取,以便操作系统可以为我们优化它(逐字节读取是邪恶的)。我们使用一个实际的字符串,但我们使用指针写入字符串:

function TEditorDeschidereDeCredite.FileToHex(FileName: string): AnsiString;
var FS:TFileStream;
    PS:PAnsiChar;
    Block:array[0..1023] of byte; // 1Kb
    len,i,pos:Integer;
    B:Byte;
const Nibbs: array[0..15] of AnsiChar = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
begin
  FS := TFileStream.Create(FileName, fmOpenRead);
  try
    Result := '';
    SetLength(Result, FS.Size * 2);
    PS := PAnsiChar(Result);
    pos := 0; // position into the result string
    len := FS.Read(Block, SizeOf(Block));
    while len <> 0 do
    begin
      for i:=0 to len-1 do
      begin
        B := Block[i];
        PS[pos] := Nibbs[B div $F];
        Inc(pos);
        PS[pos] := Nibbs[B mod $F];
        Inc(pos);
      end;
      len := FS.Read(Block, SizeOf(Block));
    end;
  finally FS.Free;
  end;
end;

PS:我使用的是 AnsiString 和 PAnsiChar,所以代码也适用于 Unicode Delphi。如果您碰巧在 Delphi 2010 上,请找到一种以当前形式 (AnsiString) 使用它的方法,这样您就可以跳过转换。

于 2010-05-12T10:47:27.457 回答