Как читать большие файлы из SQL Server? - PullRequest
0 голосов
/ 30 августа 2018

Я пытался прочитать файл (650 мегабайт) с SQL Server:

using (var reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
{
   if (reader.Read())
   {
       using (var dbStream = reader.GetStream(0))
       {
          if (!reader.IsDBNull(0))
          {
              stream.Position = 0;
              dbStream.CopyTo(stream, 256);
           }

           dbStream.Close();
         }
       }

       reader.Close();
    }

Но я получил OutOfMemoryException на CopyTo().

С небольшими файлами этот фрагмент кода работает нормально. Как я могу обработать большой файл?

Ответы [ 2 ]

0 голосов
/ 31 августа 2018

@ MatthewWatson, да, var stream = new MemoreStream (); Что не так с этим? - Кливер Макс 15 часов назад

Ваша проблема не в том, используете ли вы:

`command.ExecuteReader(CommandBehavior.SequentialAccess)` 

... кем вы являетесь, как мы можем видеть; или что размер буфера вашей потоковой копии слишком велик (на самом деле он крошечный), а вы используете MemoryStream, как вы указали в комментариях выше. Скорее всего, вы загружаете в файл размером 650 МБ дважды , один раз из SQL , а другой файл будет сохранен в MemoryStream , что приведет к исключению OutOfMemoryException .

Хотя решение состоит в том, чтобы вместо этого записывать в файловый поток, причина проблемы не была выделена в принятом ответе. Если вы не знаете причину проблемы, вы не научитесь избегать таких проблем в будущем.

0 голосов
/ 30 августа 2018

Вы можете читать и записывать данные в некоторый временный файл небольшими порциями. Вы можете увидеть пример на MSDN - Получение двоичных данных .

// 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;                      

// Open the connection and read data into the DataReader.  
connection.Open();  
SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess);  

while (reader.Read())  
{  

  // Create a file to hold the output.  
  stream = new FileStream(  
    "some-physical-file-name-to-dump-data.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();

Убедитесь, что вы используете SqlDataReader с CommandBehavior.SequentialAccess, обратите внимание на эту строку в приведенном выше фрагменте кода.

 SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess);  

Более подробную информацию о CommandBehavior enum можно найти здесь .

EDIT:

Позвольте мне прояснить себя. Я согласился с @MickyD, причина проблемы не в том, используете ли вы CommandBehavior.SequentialAccess или нет, а в одновременном чтении большого файла.

Я подчеркнул это, поскольку разработчики обычно упускают это, они, как правило, читают файлы порциями, но без установки CommandBehavior.SequentialAccess они столкнутся с другими проблемами. Хотя он уже опубликован с оригинальным вопросом, но выделен в моем ответе, чтобы дать оценку любым новичкам.

...