这是继续努力减少我的记忆负荷
How do you refill a byte array using 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阅读器时,我一直收到“未找到重建预告片.原始错误:未找到PDF startxref”错误.我相信这是因为字节数组太长并且尾随0.但由于我正在使用字节数组,所以我不会在LOH上不断构建新对象,我需要这样做.
那么我如何获得我需要的数组并将其发送到PDFReader呢?
更新
所以我查看了源代码,发现我的实际代码中有一些变量令人困惑.我基本上在循环的每次迭代中重用fileRetrievedFromDatabase对象.由于它通过引用传递,它被清除(设置为全零),然后填充PopulateFileWithPDFDataFromDatabase.然后,此对象用于创建新PDF.
如果我没有这样做,将在每次迭代中创建一个新的大字节数组,并且Large Object Heap会变满并最终抛出OutOfMemory异常.
最佳答案 您至少有两个选择:
>将您的缓冲区视为circular buffer,其中包含两个开始和结束位置的索引.
需要一个写在outByte中的最后一个字节的索引,当你到达那个索引时你必须停止读取.
>只需读取与数据数组中相同的字节数,以避免读入不属于同一文件的缓冲区的“未知”部分.
换句话说,不要将bufferSize作为最后一个参数,而是使用data.Length.
// Read the bytes into outbyte[] and retain the number of bytes returned.
retval = myReader.GetBytes(0, startIndex, outbyte, 0, data.Length);
如果数据长度为10且你的outbyte缓冲区为15,那么你应该只读取data.Length而不是bufferSize.
但是,我仍然没有看到你如何重复使用outbyte“缓冲区”,如果那就是你正在做的事情……我根本就没有根据你在答案中提供的内容进行跟踪.也许你可以准确地澄清什么是重复使用.