const PdfDefaultStorageMemoryLimit = 64 * 1024 * 1024;
type TPdfStorageBackend = (psbMemory, psbTemporaryFile);
constructor TPdfRandomAccessStore.Create(AMemoryLimit: Int64 = PdfDefaultStorageMemoryLimit; const ATemporaryDirectory: string = '');
destructor Destroy; override;
function Read(var Buffer; Count: Longint): Longint; override;
function Seek(Offset: Int64; Origin: TSeekOrigin): Int64; override;
function Write(const Buffer; Count: Longint): Longint; override;
function ReadAt(Offset: Int64; var Buffer; Count: Longint): Longint;
function WriteAt(Offset: Int64; const Buffer; Count: Longint): Longint;
procedure CopyToStream(Destination: TStream; BufferSize: Integer = 1048576);
procedure Flush;
procedure SpillToDisk;
property Backend: TPdfStorageBackend;
property MemoryBytes: Int64;
property MemoryLimit: Int64;
property PeakMemoryBytes: Int64;
property Spilled: Boolean;
property TemporaryDirectory: string;
property TemporaryFileName: string;
property SaveMemoryLimit: Int64;
property SaveTemporaryDirectory: string;
property LastSaveSpillCount: Integer;
property LastSaveLargestMemoryBuffer: Int64;
| SaveMemoryLimit | ความจุหน่วยความจำสำรองสูงสุดของที่เก็บบันทึกภายในแต่ละตัวก่อน spill ลงดิสก์; ค่า default คือ 64 MiB |
| SaveTemporaryDirectory | ไดเรกทอรีที่มีอยู่แล้วซึ่งใช้เก็บไฟล์ spill; ค่าว่างหมายถึงใช้ไดเรกทอรีชั่วคราวของโปรเซส |
| LastSaveSpillCount | จำนวนที่เก็บทำงานภายในที่ spill ระหว่าง pipeline การบันทึกครั้งล่าสุด |
| LastSaveLargestMemoryBuffer | ความจุหน่วยความจำสำรองเดี่ยวที่ใหญ่ที่สุดที่พบระหว่าง pipeline การบันทึกครั้งล่าสุด |
TPdfRandomAccessStore สืบทอดจาก TStream รองรับการอ่าน เขียน seek และกำหนดขนาดแบบลำดับปกติ นอกเหนือจาก I/O แบบระบุตำแหน่งที่ไม่ขึ้นกับ cursor
ข้อมูลยังอยู่ใน buffer หน่วยความจำที่ขยายขนาดได้ ตราบใดที่จุดสิ้นสุดเชิงตรรกะไม่เกิน MemoryLimit
การทำงานแรกที่ข้ามเพดานจะสร้างไฟล์ชั่วคราวแบบ exclusive คัดลอกไบต์เดิมครั้งเดียว ล้าง buffer หน่วยความจำ แล้วใช้ backend แบบไฟล์ต่อไปตลอดอายุของ store
แฮนเดิลชั่วคราวใช้แฟล็ก delete-on-close และ random access ไม่อนุญาตให้ใช้ร่วมกัน และถูกลบเมื่อถูกทำลายตามปกติหรือเมื่อ constructor rollback
การทำงานแต่ละครั้งถูกทำให้เป็นอนุกรมด้วย critical section ภายใน; ควรใช้ ReadAt และ WriteAt เมื่อผู้เรียกพร้อมกันหลายตัวต้องไม่แย่ง cursor แบบลำดับกัน
ส่ง store เข้า LoadCustomDocument ได้โดยตรง; block callback ของ PDFium ใช้การอ่านแบบระบุตำแหน่งและไม่ขยับ cursor ของ store
TPdf ใช้นโยบายที่ตั้งไว้กับการบันทึกหลัก, workspace post-processing ของ PDF ที่บันทึกทุกครั้ง และการจัดเตรียมระหว่างกลางของการแปลงมาตรฐาน การตรวจสอบ การเข้ารหัส DSS และ PAdES
การซ่อม xref-stream แบบ incremental ระดับ native อ่านหน้าต่าง tail และพจนานุกรมขนาดคงที่ แล้วนำการแก้ไขที่ผ่านการตรวจแล้วไปใช้ขณะคัดลอกช่วงที่ไม่เปลี่ยนแปลงเป็น chunk แบบจำกัดขนาด
MemoryBytes รายงานความจุของ buffer สำรอง ไม่ใช่ขนาดเนื้อหาเชิงตรรกะPeakMemoryBytes ไม่เกิน MemoryLimit เด็ดขาดLastSaveLargestMemoryBuffer คือขนาดของที่เก็บภายในเดี่ยวที่ใหญ่สุด ไม่ใช่ผลรวมของที่เก็บที่ active พร้อมกันTBytes ชั่วคราวที่ parser, compressor, validator หรือ signer เฉพาะตัวยังสร้างอยู่MemoryLimit ต้องอยู่ระหว่างศูนย์กับ High(Integer)FPDF_FILEACCESS สาธารณะบน Windows ยังคงจำกัดความยาวไฟล์ที่ 4 GiB แม้ store สำรองตัวจริงจะมีขนาด Int64 ที่ใหญ่กว่าTemporaryFileName ใช้เพื่อการวินิจฉัยเท่านั้น; ไฟล์ที่กำลังใช้ถูกเปิดแบบ exclusive และห้ามผู้เรียกเปิดซ้ำ
var
Store: TPdfRandomAccessStore;
begin
Pdf.SaveMemoryLimit := 16 * 1024 * 1024;
Pdf.SaveTemporaryDirectory := TPath.GetTempPath;
Pdf.SaveAs('output.pdf');
Log(Pdf.LastSaveSpillCount, Pdf.LastSaveLargestMemoryBuffer);
Store := TPdfRandomAccessStore.Create(4 * 1024 * 1024);
try
Store.CopyFrom(SourceStream, SourceStream.Size);
Store.Position := 0;
Pdf.LoadCustomDocument(Store, False);
finally
Pdf.Active := False;
Store.Free;
end;
end;