这是继续努力减少我在如何使用SqlDataReader重新填充字节数组?中提到的内存负载的文章。
所以我有一个固定大小的字节数组,例如new byte[400000]。我将在这个数组中放置不同大小(小于400000)的pdf文件。
伪代码如下:
上述代码的问题在于,当我尝试访问PDF阅读器时,总是会出现“找不到重建尾部。原始错误:找不到PDF startxref”的错误。我认为这是因为字节数组太长并且有尾随0。但由于我正在使用字节数组,以便我不需要在LOH上不断构建新对象,所以我需要这样做。
那么我该如何获取我需要的数组片段并将其发送到PDFReader呢?
更新:
所以我看了一下源代码,意识到我从我的实际代码中得到了一些混淆的变量。在循环的每次迭代中,我基本上是在重用从数据库中检索到的文件对象。由于它是通过引用传递的,它会被清除(设置为全零),然后填充PopulateFileWithPDFDataFromDatabase。然后使用此对象创建新的PDF。
如果我没有这样做,就会在每次迭代中创建一个新的大型字节数组,而大对象堆栈会变满,并最终抛出OutOfMemory异常。
所以我有一个固定大小的字节数组,例如new byte[400000]。我将在这个数组中放置不同大小(小于400000)的pdf文件。
伪代码如下:
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阅读器时,总是会出现“找不到重建尾部。原始错误:找不到PDF startxref”的错误。我认为这是因为字节数组太长并且有尾随0。但由于我正在使用字节数组,以便我不需要在LOH上不断构建新对象,所以我需要这样做。
那么我该如何获取我需要的数组片段并将其发送到PDFReader呢?
更新:
所以我看了一下源代码,意识到我从我的实际代码中得到了一些混淆的变量。在循环的每次迭代中,我基本上是在重用从数据库中检索到的文件对象。由于它是通过引用传递的,它会被清除(设置为全零),然后填充PopulateFileWithPDFDataFromDatabase。然后使用此对象创建新的PDF。
如果我没有这样做,就会在每次迭代中创建一个新的大型字节数组,而大对象堆栈会变满,并最终抛出OutOfMemory异常。
data.Length
而不是bufferSize
,因为根据你的解释,data.Length
应该始终小于bufferSize
。此外,由于您正在重复使用缓冲区,不同大小的文件可能会导致来自旧文件和较大文件的缓冲区中的“垃圾”,这可能会“损坏”您的文件。 - Kiril