Это продолжение продолжающейся борьбы за сокращение моего упоминания о загрузке памяти в
Как пополнить байтовый массив с помощью SqlDataReader?
Итак, у меня есть байтовый массив заданного размера, для этого примера я скажу новый байт [400000]. Внутри этого массива я буду размещать PDF-файлы разных размеров (менее 400000).
код псевдо будет:
public void Run()
{
byte[] fileRetrievedFromDatabase = new byte[400000];
foreach (var document in documentArray)
{
// Refill the file with data from the database
var currentDocumentSize = PopulateFileWithPDFDataFromDatabase(fileRetrievedFromDatabase);
var reader = new iTextSharp.text.pdf.PdfReader(fileRetrievedFromDatabase.Take((int)currentDocumentSize ).ToArray());
pageCount = reader.NumberOfPages;
// DO ADDITIONAL WORK
}
}
private int PopulateFileWithPDFDataFromDatabase(byte[] fileRetrievedFromDatabase)
{
// DataAccessCode Goes here
int documentSize = 0;
int bufferSize = 100; // Size of the BLOB buffer.
byte[] outbyte = new byte[bufferSize]; // The BLOB byte[] buffer to be filled by GetBytes.
myReader = logoCMD.ExecuteReader(CommandBehavior.SequentialAccess);
Array.Clear(fileRetrievedFromDatabase, 0, fileRetrievedFromDatabase.Length);
if (myReader == null)
{
return;
}
while (myReader.Read())
{
documentSize = myReader.GetBytes(0, 0, null, 0, 0);
// Reset the starting byte for the new BLOB.
startIndex = 0;
// Read the bytes into outbyte[] and retain the number of bytes returned.
retval = myReader.GetBytes(0, startIndex, outbyte, 0, bufferSize);
// Continue reading and writing while there are bytes beyond the size of the buffer.
while (retval == bufferSize)
{
Array.Copy(outbyte, 0, fileRetrievedFromDatabase, startIndex, retval);
// Reposition the start index to the end of the last buffer and fill the buffer.
startIndex += retval;
retval = myReader.GetBytes(0, startIndex, outbyte, 0, bufferSize);
}
}
return documentSize;
}
Проблема с приведенным выше кодом заключается в том, что я продолжаю получать сообщение об ошибке «Перестроить трейлер не найден. Исходная ошибка: PDF startxref not found» при попытке доступа к программе чтения PDF. Я считаю, что это потому, что байтовый массив слишком длинный и имеет конечные 0. Но поскольку я использую байтовый массив, чтобы не создавать новые объекты в LOH, мне нужно это сделать.
Итак, как мне получить только тот фрагмент массива, который мне нужен, и отправить его в PDFReader?
Обновлено
Так что я посмотрел на источник и понял, что у меня есть некоторые переменные из моего реального кода, которые сбивают с толку. Я в основном повторно использую объект fileRetrievedFromDatabase в каждой итерации цикла. Поскольку он передается по ссылке, он очищается (устанавливается на все нули), а затем заполняется в PopulateFileWithPDFDataFromDatabase. Этот объект затем используется для создания нового PDF.
Если бы я не сделал это таким образом, новый крупный байтовый массив создавался бы на каждой итерации, и куча больших объектов заполнялась и в конечном итоге создавала исключение OutOfMemory.