2

バイナリ ファイル (zip ファイル) を 16 進数表現に変換し、それを varbinary(max) 関数パラメーターとして sql-server に送信する必要があります。

完全な例 (非常に小さなファイルを使用) は次のとおりです。

1)私のファイルには次のビットが含まれています0000111100001111

2)すぐに変換する手順が必要です0F0F

0x0F0F3)パラメータとして渡すSQLサーバー関数を呼び出します

問題は、大きなファイル (平均ファイル サイズが 100 KB のファイルであっても、最大 100 MB まで) があることです。そのため、これを行うための最速の方法が必要です。

別の言い方: 文字列を作成する必要があります

'0x'+BinaryDataInHexadecimalRepresentation

最も効率的な方法で。(注:ファイルをすぐに開いて16進数の文字列を取得する方法があるかもしれないので、この場合、必要なのは「この方法」があればそれを使用することだけです)。

関連する質問: 16 進数データを SQL サーバーに渡す

更新:コメントを読んだ後、ここにさらに情報を追加する必要があると思います。T-SQL テキスト コマンドを使用してバイナリ データをストアド プロシージャに送信しようとする理由は、この方法でサーバーのオーバーヘッドをいくらか取り除くためです。ストアド プロシージャはバイナリ データを受け取り、それをファイルに書き込みます (このが最終目標です)。DAC コンポーネントを使用すると、biray データをサーバーに簡単に送信できますが、その場合、一時テーブルを使用してデータを保存し、このデータをストアド プロシージャに送信してファイルを書き込む必要があります。

したがって、アイデアは次のとおりです。

1)T-SQLの「長い」コマンドを使用する:ファイルを読み取って16進数に変換して長いコマンドを準備する必要があるため、クライアントのオーバーヘッドが増加します。SQLサーバーはバイナリデータを受信して​​ストアドファンクションで処理するだけなので、サーバーのオーバーヘッドが少なくなります

2) DAC の使用: SQL サーバーの一時テーブルを通過する必要があるため、サーバーのオーバーヘッドが大きくなります

サーバーを Web ドキュメント サーバーとして使用しているため (トリックです)、サーバーのオーバーヘッドを減らしたいと考えています。とにかく私が間違っている可能性があり、(2)とにかく(1)よりも優れたテクニックです

4

1 に答える 1

1

さて、ここに私が考えることができるのと同じくらい速く変換を行うオプションがあります.

コードの特徴:

  • 文字列の割り当ては 1 つだけです (したがって、再割り当ても移動もコピーもありません)。
  • ファイルからの高速読み取り。

1 バイトが正確に 2 つの 16 進数文字に変換されることがわかっているため、結果の文字列はファイルのサイズのちょうど 2 倍である必要があることがわかります。必要なサイズの文字列を割り当ててから、OS が最適化できるように十分な大きさのブロックでファイルから読み取ります (バイトごとの読み取りは悪です)。実際の文字列を使用しますが、ポインターを使用して文字列に書き込みます。

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 に答える