バイナリ データの取得Retrieving Binary Data

既定では、データの行全体が使用可能になるとすぐに、DataReader によって受信データが行として読み込まれます。By default, the DataReader loads incoming data as a row as soon as an entire row of data is available. バイナリ ラージ オブジェクト (BLOB) には、1 行に収まらない数ギガバイトのデータが含まれる場合があるため、別の処理が必要です。Binary large objects (BLOBs) need different treatment, however, because they can contain gigabytes of data that cannot be contained in a single row. Command.ExecuteReader メソッドには、CommandBehavior 引数を受け取って DataReader の既定の動作を変更するオーバーロードがあります。The Command.ExecuteReader method has an overload that will take a CommandBehavior argument to modify the default behavior of the DataReader. ExecuteReader メソッドに SequentialAccess を渡すと、データの行を読み込む代わりに、データを受け取った時点で順次読み込むように、DataReader の既定の動作を変更できます。You can pass SequentialAccess to the ExecuteReader method to modify the default behavior of the DataReader so that instead of loading rows of data, it will load data sequentially as it is received. これは BLOB やその他の大きなデータ構造を読み込む場合に理想的な処理です。This is ideal for loading BLOBs or other large data structures. この動作は、データ ソースによって異なる場合があります。Note that this behavior may depend on your data source. たとえば、Microsoft Access から BLOB を返すと、受け取ったデータから順に読み込むのではなく、BLOB 全体をメモリに読み込みます。For example, returning a BLOB from Microsoft Access will load the entire BLOB being loaded into memory, rather than sequentially as it is received.

SequentialAccess を使用するように DataReader を設定するときは、返されたフィールドにアクセスする順序に注意してください。When setting the DataReader to use SequentialAccess, it is important to note the sequence in which you access the fields returned. 使用可能になるとすぐに行全体を読み込む DataReader の既定の動作では、次の行が読み取られるまでは、返されたフィールドに任意の順序でアクセスできます。The default behavior of the DataReader, which loads an entire row as soon as it is available, allows you to access the fields returned in any order until the next row is read. しかし、SequentialAccess を使用しているときは、DataReader によって返された各フィールドに順番にアクセスする必要があります。When using SequentialAccess however, you must access the fields returned by the DataReader in order. たとえば、クエリが 3 つの列 (3 番目の列は BLOB) を返す場合、最初のフィールドおよび 2 番目のフィールドの値は、3 番目のフィールドの BLOB データにアクセスする前に返す必要があります。For example, if your query returns three columns, the third of which is a BLOB, you must return the values of the first and second fields before accessing the BLOB data in the third field. 最初のフィールドまたは 2 番目のフィールドの前に 3 番目のフィールドにアクセスした場合は、最初のフィールドと 2 番目のフィールドの値は使用できなくなります。If you access the third field before the first or second fields, the first and second field values are no longer available. これは、SequentialAccess によって、DataReader はデータを順番に返すように変更されており、DataReader による読み取りが通過した後のデータは使用できなくなるためです。This is because SequentialAccess has modified the DataReader to return data in sequence and the data is not available after the DataReader has read past it.

BLOB フィールドのデータにアクセスするときは、DataReaderGetBytes 型または GetChars 型のアクセサーを使用します。これらのアクセサーでは、データは配列に設定されます。When accessing the data in the BLOB field, use the GetBytes or GetChars typed accessors of the DataReader, which fill an array with data. 文字データには GetString を使用することもできます。ただし、You can also use GetString for character data; however. システム リソースを節約するためには、BLOB 値全体を 1 つの文字列変数に読み込むことは望ましくありません。to conserve system resources you might not want to load an entire BLOB value into a single string variable. 特定のバッファー サイズのデータを返すように指定する代わりに、返されたデータから読み込む先頭バイトまたは先頭文字の開始位置を指定できます。You can instead specify a specific buffer size of data to be returned, and a starting location for the first byte or character to be read from the returned data. GetBytesGetChars では、返されたバイト数または文字数を表す long 値が返されます。GetBytes and GetChars will return a long value, which represents the number of bytes or characters returned. GetBytes または GetChars に null 配列を渡した場合、返される long 値は BLOB の総バイト数または総文字数になります。If you pass a null array to GetBytes or GetChars, the long value returned will be the total number of bytes or characters in the BLOB. オプションで、データ読み込みの開始位置を示す、配列内のインデックスを指定できます。You can optionally specify an index in the array as a starting position for the data being read.

Example

次の例では、Microsoft SQL Server の pubs サンプル データベースから、発行者 ID とロゴを取得します。The following example returns the publisher ID and logo from the pubs sample database in Microsoft SQL Server. 発行者 ID (pub_id) は文字フィールドであり、ロゴはイメージ、つまり、BLOB です。The publisher ID (pub_id) is a character field, and the logo is an image, which is a BLOB. logo フィールドはビットマップなので、この例では、GetBytes を使用してバイナリ データを返します。Because the logo field is a bitmap, the example returns binary data using GetBytes. フィールドには順番にアクセスする必要があるため、現在の行のデータに対して発行者 ID はロゴの前にアクセスされることに注意してください。Notice that the publisher ID is accessed for the current row of data before the logo, because the fields must be accessed sequentially.

' Assumes that connection is a valid SqlConnection object.  
Dim command As SqlCommand = New SqlCommand( _  
  "SELECT pub_id, logo FROM pub_info", connection)  
  
' Writes the BLOB to a file (*.bmp).  
Dim stream As FileStream
' Streams the binary data to the FileStream object.  
Dim writer As BinaryWriter
' The size of the BLOB buffer.  
Dim bufferSize As Integer = 100
' The BLOB byte() buffer to be filled by GetBytes.  
Dim outByte(bufferSize - 1) As Byte
' The bytes returned from GetBytes.  
Dim retval As Long
' The starting position in the BLOB output.  
Dim startIndex As Long = 0
  
' The publisher id to use in the file name.  
Dim pubID As String = ""
  
' Open the connection and read data into the DataReader.  
connection.Open()  
Dim reader As SqlDataReader = command.ExecuteReader(CommandBehavior.SequentialAccess)  
  
Do While reader.Read()  
  ' Get the publisher id, which must occur before getting the logo.  
  pubID = reader.GetString(0)  
  
  ' Create a file to hold the output.  
  stream = New FileStream( _  
    "logo" & pubID & ".bmp", FileMode.OpenOrCreate, FileAccess.Write)  
  writer = New BinaryWriter(stream)  
  
  ' Reset the starting byte for a new BLOB.  
  startIndex = 0  
  
  ' Read bytes into outByte() and retain the number of bytes returned.  
  retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize)  
  
  ' Continue while there are bytes beyond the size of the buffer.  
  Do While retval = bufferSize  
    writer.Write(outByte)  
    writer.Flush()  
  
    ' Reposition start index to end of the last buffer and fill buffer.  
    startIndex += bufferSize  
    retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize)  
  Loop  
  
  ' Write the remaining buffer.  
  writer.Write(outByte, 0 , retval - 1)  
  writer.Flush()  
  
  ' Close the output file.  
  writer.Close()  
  stream.Close()  
Loop  
  
' Close the reader and the connection.  
reader.Close()  
connection.Close()  
// Assumes that connection is a valid SqlConnection object.  
SqlCommand command = new SqlCommand(  
  "SELECT pub_id, logo FROM pub_info", connection);  
  
// Writes the BLOB to a file (*.bmp).  
FileStream stream;
// Streams the BLOB to the FileStream object.  
BinaryWriter writer;
  
// Size of the BLOB buffer.  
int bufferSize = 100;
// The BLOB byte[] buffer to be filled by GetBytes.  
byte[] outByte = new byte[bufferSize];
// The bytes returned from GetBytes.  
long retval;
// The starting position in the BLOB output.  
long startIndex = 0;
  
// The publisher id to use in the file name.  
string pubID = "";
  
// Open the connection and read data into the DataReader.  
connection.Open();  
SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess);  
  
while (reader.Read())  
{  
  // Get the publisher id, which must occur before getting the logo.  
  pubID = reader.GetString(0);
  
  // Create a file to hold the output.  
  stream = new FileStream(  
    "logo" + pubID + ".bmp", FileMode.OpenOrCreate, FileAccess.Write);  
  writer = new BinaryWriter(stream);  
  
  // Reset the starting byte for the new BLOB.  
  startIndex = 0;  
  
  // Read bytes into outByte[] and retain the number of bytes returned.  
  retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize);  
  
  // Continue while there are bytes beyond the size of the buffer.  
  while (retval == bufferSize)  
  {  
    writer.Write(outByte);  
    writer.Flush();  
  
    // Reposition start index to end of last buffer and fill buffer.  
    startIndex += bufferSize;  
    retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize);  
  }  
  
  // Write the remaining buffer.  
  writer.Write(outByte, 0, (int)retval);  
  writer.Flush();  
  
  // Close the output file.  
  writer.Close();  
  stream.Close();  
}  
  
// Close the reader and the connection.  
reader.Close();  
connection.Close();  

関連項目See also