这是一个老问题,我一直在使用上面的 Anton Bakulev 的答案,直到遇到我的数据实际上大于 int curPos 可以处理的 2GB 的情况。当我尝试将 bufferIndex 参数更改为 0 时,超出 bufferSize 的任何内容都已损坏。 (此外,如此小的缓冲区大小使得加载 2MB 以上的任何内容都成为一种痛苦)。
不,您可能不应该在数据库的单个列中包含超过 2GB 的数据。尽量避免这种情况。但以防万一,这里有一个更健壮、更精简的代码版本,作为 SqlDataReader 扩展方法:
public static byte[] ParseStrictByteArray(this SqlDataReader reader, string columnName)
{
int colIdx = reader.GetOrdinal(columnName);
long size = reader.GetBytes(colIdx, 0, null, 0, 0);
byte[] imageValue = new byte[size];
// essentially, we are loading all this data in memory, either way... Might as well do it in one swoop if we can
int bufferSize = (int)Math.Min(int.MaxValue, size);
//int.MaxValue = 2,147,483,647 = roughly 2 GB of data, so if the data > 2GB we have to read in chunks
if(size > bufferSize){
long bytesRead = 0;
int position = 0;
//we need to copy the data over, which means we DON'T want a full copy of all the data in memory.
//We need to reduce the buffer size (but not too much, as multiple calls to the reader also affect performance a lot)
bufferSize = 104857600; //this is roughly 100MB
byte[] buffer = new byte[bufferSize];
while (bytesRead < size)
{
if (size - bytesRead < bufferSize)
bufferSize = Convert.ToInt32(size - bytesRead);
bytesRead += reader.GetBytes(colIdx, position, buffer, 0, bufferSize);
//shift the buffer into the final array
Array.Copy(buffer, 0, imageValue, position, bufferSize);
position += bufferSize;
}
}
else
{
//single read into the image buffer
reader.GetBytes(colIdx, 0, imageValue, 0, bufferSize);
}
return imageValue;
}