2012-02-02 4 views
4

にバイト[]配列の一部をコピーする。これは、だから私はこのために、設定されたサイズでバイト配列を持っている How do you refill a byte array using SqlDataReader?PDFReader

に私の記憶の負荷言及を軽減するための継続的な闘争の継続でありますたとえば、私は新しいバイト[400000]と言うでしょう。この配列の中で、私はさまざまなサイズのPDFを配置します(400000未満)。

擬似コードは次のようになります。私がアクセスしようとすると、エラー:「PDFのstartxrefが見つかりません。見つからないトレーラーを再構築し、元のエラー」

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リーダー。私はそれがバイト配列が長すぎると0の後ろにあるためだと思う。しかし、バイト配列を使っているので、LOH上に新しいオブジェクトを連続的に構築しているわけではないので、これを行う必要があります。

どのようにして必要な配列の部分だけを取得し、それをPDFReaderに送信すればよいですか?

を更新しました

だから私は、ソースを見て、私は混乱した私の実際のコードからいくつかの変数を持っていたが実現。私は基本的に、ループの各繰り返しでfileRetrievedFromDatabaseオブジェクトを再利用しています。それは参照渡しであるため、クリアされ(0に設定されます)、PopulateFileWithPDFDataFromDatabaseに入力されます。このオブジェクトを使用して新しいPDFを作成します。

私がこのようにしなかった場合、すべての反復で新しい大きなバイト配列が作成され、ラージオブジェクトヒープがいっぱいになり、最終的にOutOfMemory例外がスローされます。

答えて

1

明らかに、whileループは現在構造化されていますが、最後の繰り返しでデータをコピーしていませんでした。これを追加する必要があります:

if (outbyte != null && outbyte.Length > 0 && retval > 0) 
{ 
    Array.Copy(outbyte, 0, currentDocument.Data, startIndex, retval); 
} 

私は間違いなくリファクタリングする必要がありますが、今は動作しています。

+0

また、バイトの最後にゼロがある場合、PDFReaderは無視します。 – Cyfer13

1

あなたは、少なくとも2つのオプションがあります。

  1. は、開始位置と終了のための2つのインデックスを持つcircular bufferのようなあなたのバッファを扱います。 は、outByteに書き込まれた最後のバイトのインデックスを必要とし、そのインデックスに到達すると読み込みを停止する必要があります。
  2. dataアレイの場合と同じバイト数を読み込んで、同じファイルに属していないバッファの「未知の」部分を読み込まないようにしてください。

つまり、bufferSizeを最後のパラメータとして使用する代わりに、data.Lengthを指定します。

// Read the bytes into outbyte[] and retain the number of bytes returned. 
retval = myReader.GetBytes(0, startIndex, outbyte, 0, data.Length); 

data長さが10であり、あなたのoutbyteバッファが15であれば、あなただけのdata.LengthないbufferSizeをお読みください。

しかし、私はあなたがしていることであれば、アウトバウンド "バッファ"をどのように再利用しているのかまだ分かりません...私はあなたの答えで提供したものに基づいていません。たぶん、再利用されているものを明確にすることができます。

+0

はすばやい応答を高く評価しますが、私はどこでバッファサイズを超えて読み取ったのか分かりません。 – Cyfer13

+0

私は自分の答えを更新しようとしましたが、更新するよりも速くコメントしてくれたと思います。私はあなたが実際にどこに 'データ'を 'アウトバイト'に入れるのかは分かりませんが、そうしたときには 'bufferSize'の代わりに' data.Length'だけを読むようにしなければなりません。説明すると、 'data.Length'は常に' bufferSize'より小さくなければなりません。さらに、バッファを再利用しているため、サイズの異なるファイルは、古いファイルや大きいファイルのバッファに「迷惑メール」が入り、ファイルが破損する可能性があります。 – Kiril

+0

あなたが言及している行については、データの長さを取得する方法はないと思っています。これが最初に読み込んでから実際に読み取ったデータの量を返すのです人口が多い。私は、すべてのpdfが最大サイズよりも小さくなるため、byte []が満たされるたびにゼロの後になることがあるという事実を知っています。最大サイズはpdf * 1.1で決まります。その論理に従って – Cyfer13

関連する問題