Sivujen laskemisen 1,4 Gt:n skannatussa arkistossa pitäisi olla halpaa. Kutsu komentoa LoadFromFile tuolle tiedostolle, niin sen halpuus lakkaa: HotPDF jäsentää ristiinviittaustiedot ja rakentaa muistissa olevan objektin jokaiselle asiakirjan useista sadoista tuhansista epäsuorista objekteista, ja 32-bittinen työntekijä osuu 2 Gt:n osoiteavaruuden kattoon jossain tuon jäsennyksen keskivaiheilla. Haluamasi toiminto, sivumäärä, ei koskaan tarvinnut mitään näistä kohteista. Se tarvitsi sivupuun, ei mitään muuta. Tuo kuilu työn pyytämän ja täyden latauksen tuottaman välillä on koko syy siihen, miksi Direct File API on olemassa
Direct File API antaa Delphille ja C++Builderille tiedostotason pääsyn PDF:ään: sivumäärät, kopiot, salauksen purku, inkrementaaliset liitteet lukevat kaikki levyltä, mitä ne todella tarvitsevat, sen sijaan, että rekonstruoisivat koko asiakirjamallin RAM-muistiin. Taito on sovittaa kukin työ kevyimpään tasoon, joka voi vastata siihen. Hanki oikea ottelu ja palvelu pitää litteää muistia missä tahansa syöttökoossa. Jos teet väärin, ensimmäinen ylimitoitettu tiedosto vie työntekijän alas
Mitä täysi kuorma maksaa sinulle
LoadFromFile ei ole vihollinen. Se ansaitsee muistinsa: kun puu on RAM-muistissa, sinulla on satunnainen pääsy jokaiseen sivuun ja jokaiseen objektiin, mitä komento InsertPagesFromDocument, MovePage ja uudelleensarjoittaminen SaveLoadedDocument-toiminnolla edellyttävät. Aidolle rakenneuudistukselle ei ole oikotietä; sinun on pidettävä asiakirjasta kiinni, jotta voit järjestää sen uudelleen
Vaikeudet alkavat, kun syöttökoot eivät ole sinun hallinnassasi. Asiakkaiden lataukset, skannerien tulostus ja vuosikymmenen takaiset arkistot sivuuttavat sen, mitä testikorpuksesi olettikaan. Lataa jokainen syöte ehdoitta ja muistikattonsi määräytyy suurimman yksittäisen tiedoston perusteella, jonka kukaan koskaan lähettää. Jäsennysaika seuraa objektimäärää ja muisti asettuu moninkertaiseksi tiedostokokoon nähden objektirakenteiden ja purettujen virtojen laskemisen jälkeen, joten gigatavu levyllä voi tarkoittaa useiden gigatavujen residenttiä
Kääntäminen uudelleen 64-bittiselle nostaa osoiteavaruuden kattoa, mutta jättää laskun ennalleen. Työntekijä polttaa edelleen sekunteja prosessoria ja kerrannaisen RAM-muistissa olevaa tiedostoa vastatakseen kysymykseen, johon tiedoston oma rakenne olisi voinut vastata millisekunneissa. Samanaikaisuuden alla matematiikka muuttuu vihamieliseksi: neljä suurta kuormaa, jotka kulkevat samanaikaisesti, jakavat yhden muistibudjetin, ja läpimeno karsiutuu juuri silloin, kun jono on syvin ja sinulla on vähiten varaa siihen
Tiedoston lukeminen kahvan kautta
Vain luku -taso avaa tiedoston kahvana, vastaa sitä koskeviin rakennekysymyksiin ja sulkee sen. Ei objektipuuta, ei sivun hahmontamista, ei muistia, joka kasvaa syötteen mukana
var
Pdf: THotPDF;
Handle, PageCount: Integer;
begin
Pdf := THotPDF.Create(nil);
try
Handle := Pdf.DAOpenFileReadOnly('archive-2026-06.pdf', '');
if Handle > 0 then
try
PageCount := Pdf.DAGetPageCount(Handle);
RouteByPageCount('archive-2026-06.pdf', PageCount);
finally
Pdf.DACloseFile(Handle);
end;
finally
Pdf.Free;
end;
end;
Kolme tottumusta pitävät tämän tason rehellisenä. Tarkista ensin palautusarvo. Ei-positiivinen kahva tarkoittaa avoimen epäonnistunutta, ja laukaisu DAGetPageCount kuolleessa kahvassa on sellainen virhe, joka pysyy piilossa siihen päivään asti, kunnes asiakas lähettää virheellisesti muotoillun tiedoston. Toiseksi, yhdistä jokainen onnistunut avaus komennon DACloseFile kanssa finally-lohkon sisään; palvelu, joka vuotaa kahvoista ei kaadu, se vain mätänee, mikä on huonompi. Kolmanneksi kunnioita sitä, mitä salasanaparametri todella tekee. DAOpenFileReadOnly hyväksyy sellaisen, mutta salattujen syötteiden kohdalla se putoaa hiljaa täyteen jäsennykseen sivumäärän lukemiseksi, jolloin litteän muistin takuu haihtuu. Reititä suojatut tiedostot ensin komennon DecryptFile läpi, niin loppu putki pysyy halpana
Sama luotain kaksinkertaistuu triageporttina. Tiedostot näyttävät virheellisesti leimatuilta, puoliksi ladatuilta tai jostain aivan muusta muodosta uudelleennimetyiltä, ja DAOpenFileReadOnly-tarkistus hylkää ne kaikki etuovella millisekunneissa, virhe on kiinnitetty loukkaavaan tiedostoon. Vaihtoehtona on antaa roskatiedoston ratsastaa syvälle jonotyöntekijään ja räjäyttää sielä, missä syötteen aiheuttaman syötteen purkaminen voi maksaa iltapäivän
Kopioi, pura salaus ja salaa kokonaisia tiedostoja
Toinen taso siirtää ja muuntaa kokonaisia tiedostoja koskaan paljastamatta niiden sisäelimiä. Näihin soittoihin imuputket nojaavat eniten
// Rakenteellinen kopio: validate-and-move jäsentämättä objektipuuta
Status := Pdf.DACopyFile('incoming\statement.pdf', 'verified\statement.pdf');
LogDirectFileStatus('copy', Status);
// Pura kopioinnin aikana: Direct File-reitti suojattuihin syötteisiin
Status := Pdf.DecryptFile('incoming\protected.pdf',
'verified\plain.pdf', 'batch-password');
LogDirectFileStatus('decrypt-copy', Status);
// Salaa kopioinnin aikana: suojaa tuloste ilman täyttä latausta
Status := Pdf.EncryptFile('verified\statement.pdf',
'outbound\statement.pdf', 'owner-secret', '', aes256, [prPrint]);
LogDirectFileStatus('encrypt-copy', Status);
Jokainen kutsu ansaitsee paikkansa. DACopyFile on validoitu kopio karanteenihakemistosta hallittuun varastoon: se avaa ja indeksoi PDF-rakenteen edetessään, joten katkaistu tai ei-PDF-syöte epäonnistuu juuri täällä eikä kolmessa vaiheessa myöhemmin. DecryptFile kirjoittaa puretun kopion suoraa AES-256-uudelleenkirjoituspolkua pitkin, joka ohittaa objektipuun aina, kun syöte sallii, suuren tiedoston vastine lataa ja tallentaa uudelleen -salauksen purkukululle, jota on käsitelty AES-256-salausta koskevassa artikkelissa. EncryptFile suorittaa saman liikkeen päinvastoin soveltamalla salasanasuojausta tiedostotason kopion aikana avaintyyppi- ja käyttöoikeusparametreilla, joita muistissa oleva polku jo käyttää
Muutosten liittäminen uudelleenkirjoittamisen sijaan
ISO 32000-1 §7.5.6:ssa määritelty lisäpäivitys on kolmas taso. Alkuperäiset tavut pysyvät paikoillaan levyllä, ja kaikki uudet tai muokatut objektit liitetään niiden jälkeen, ja niitä seuraa uusi ristiinviittausosa, joka ketjuuntuu takaisin alkuperäiseen. 900 megatavun arkistolle, johon on lisättävä yksi sivu, kirjoituskustannus on delta, ei koko tiedosto
// Liitä tarkastussivu suureen arkistoon kirjoittamatta sitä uudelleen
Pdf.BeginIncrementalUpdate('archive-2026-06.pdf');
Pdf.AddPage;
Pdf.CurrentPage.SetFont('Arial', [], 10);
Pdf.CurrentPage.TextOut(50, 760, 0, 'Processed by intake service 2026-06-11');
Pdf.SaveIncrementalUpdate('archive-2026-06-stamped.pdf'); // original bytes + delta
Tässä on väliä kahdella kurinpitopisteellä. BeginIncrementalUpdate:n on osoitettava alkuperäiseen tiedostoon, koska liitetty ristiinviittaustieto ketjutetaan takaisin sen sisällä oleviin tavusiirtymiin. Ja malli on liitettävä vain suunnittelultaan: jokainen inkrementaalinen tallennus kasvattaa tiedostoa, ei koskaan kutista sitä. Öisin leimattu asiakirja paisuu ilman rajoitusta, kunnes säännöllinen sarjallistus ladataan ja kirjoitetaan se takaisin SaveLoadedDocument-ohjelman kautta tiivistää sen. Tämä sama vain lisättävä luonne tekee vähittäisestä päivittämisestä ainoan turvallisen tavan koskettaa digitaalisesti allekirjoitettua asiakirjaa, joka on digitaalisia allekirjoituksia ja PAdES:tä käsittelevässä artikkelissa tarkasteltu rajoitus. Taustalla oleva ristiinviittauskoneisto saa oman käsittelynsä objektivirtoja ja inkrementaalisia päivityksiä käsittelevässä artikkelissa
Vain liitetään -tallenuksissa on ansa, joka luisuu useimpien arvostelujen ohi. Alkuperäiset tavut pysyvät tiedostossa kenen tahansa halukkaiden luettavissa. Inkrementaalinen päivitys, joka "korvaa" sivun, ei poista vanhaa; se korvaa sen nykyisessä revisiossa, kun taas edellinen revisio on siellä, täysin palautettavissa. Inkrementaaliset päivitykset ovat siis väärä työkalu arkaluonteisen sisällön poistamiseen. Jotta vastaanottaja voi todella pudottaa historian, jota hän ei saisi koskaan nähdä, tarvitset täyden sarjallistuksen uudelleen: LoadFromFile, jota seuraa SaveLoadedDocument, joka kirjoittaa vain nykyisen tilan ja jättää haudatut versiot taakseen
Tason sovittaminen toimintoon
Valintalogiikka on riittävän lyhyt pidettäväksi päässäsi, ja se kannattaa koodata selkeänä reitityspäätöksenä putken yläosassa sen sijaan, että kunkin työn annettaisiin improvisoida oma polkunsa. Tarvitsemasi toimenpide päättää tason:
- Laskenta, tarkistus tai luokittelu avaa kahvan:
DAOpenFileReadOnly,DAGetPageCount,DACloseFile - Koko tiedoston siirtäminen, salauksen purkaminen tai salaaminen pysyy tiedostotasolla komennon
DACopyFile,DecryptFiletaiEncryptFilekanssa - Sivujen uudelleenjärjestely tai asiakirjojen yhdistäminen vaatii täyden kuorman:
LoadFromFile, sittenInsertPagesFromDocumenttaiMovePageja sittenSaveLoadedDocument - Pienen deltan lisääminen valtavaan tai allekirjoitettuun tiedostoon kutsuu komentoa
BeginIncrementalUpdateja tallentaa
Sekoitetut putkistot menestyvät hyvin, kun täyden kuorman radan eteen laitetaan kokokynnys. Lähetä mikä tahansa muutaman sadan megatavun yli Direct File-tasojen kautta ja varaa koko kuorma aitoa rakenneuudistusta varten 64-bittiselle työntekijälle, jolla on todellinen muistibudjetti. Kynnys muuttaa muistin loppumisen aiheuttaman kaatumisen reitityspäätökseksi, jonka voit nähdä ja virittää
Minkä tahansa tason käsitteleekään työ, kirjoita sen tulos väliaikaiseen nimeen ja nimeä se paikalleen vasta, kun tulos vahvistetaan. Lopullisen nimen alla istuva puoliksi kirjoitettu tiedosto näyttää täsmälleen hyvältä liukuhihnan seuraavaan vaiheeseen, ja Direct File-kutsut tekevät tarkistuksesta halvan: lähdön vahvistaminen on yksilinjainen kahva-anturi
Direct File API toimitetaan osana Delphin ja C++Builderin HotPDF Component-komponenttia. Tuotesivulla on linkki täyteen funktioviitteeseen, mukaan lukien tässä esitetyt lisäpäivityskutsut