HotPDF, yüklenmiş bir belgeyi bir insanın okuyup düzenlemesi için tasarlanmış tanılama biçiminde kaydedebilir ve siz dosyayı düzenledikten sonra onu onarabilir. SaveLoadedDocumentDiagnostic, belgeyi belirlenimci (deterministic) sözlük sırasıyla, her nesneyi normal bir dolaylı nesne olarak, nesne akışı olmadan, çapraz referans akışı olmadan ve doğrusallaştırma olmadan yazar. RepairDiagnosticDocument ise ardından düzenlemenizin geçersiz kıldığı bayt ofsetlerini, akış uzunluklarını, çapraz referans tablosunu ve treyleri yeniden oluşturur
Bu ikili tek bir iş akışı için var: bir PDF'nin içinde gerçekte ne olduğunu anlamak veya düzeltmek. Bir render sorununu hata ayıklamış her geliştirici, dosyayı açıp bir sözlükteki bir sayıyı değiştirip sonucuna bakmak istemiştir. Normal bir PDF'de bu imkansızdır, çünkü içerik nesne akışlarına sıkıştırılmıştır ve eklediğiniz her bayt, bir çapraz referans tablosunun tam olarak kaydettiği ofsetleri kaydırır
Bir Tanılama Kaydını Farklı Kılan Nedir?
Altı ayar birlikte değişir. Sözlük anahtarları belirlenimci sırayla yazılır, bu yüzden aynı belgenin iki kaydı karşılaştırılabilir dosyalar üretir. Tanılama çıktı modu yapıyı açıklar. Tam yeniden yazma zorunlu kılınır, bu yüzden hiçbir şey dokunulmamış artımlı bir revizyon olarak taşınmaz. Doğrusallaştırma kapalıdır, çünkü doğrusallaştırılmış bir dosya bir okuyucu için değil bir web görüntüleyicisi için düzenlenmiştir. Çapraz referans akışları kapalıdır, bu yüzden tablo düz metindir. Ve nesne akışları kapalıdır, bu yüzden hiçbir nesne sıkıştırılmış bir kapsayıcının içinde gizlenmez
Sonuç, başlığı olağan %PDF- imzasının yanında bir tanılama işareti taşıyan ve gövdesinde herhangi bir düzenleyicide sayfa sayfa gezinebileceğiniz bir dosyadır. Nesneler art arda görünür, sözlükler okunaklıdır ve içerik akışları bulabileceğiniz yerlerde durur. Onarım aracı bu işareti kontrol eder ve onu taşımayan dosyaları reddeder, çünkü normal bir PDF'nin kompakt yapısı bir bayt aralığı onarıcısının yorumlamaya çalışması gereken bir şey değildir
uses
HPDFDoc;
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('invoice.pdf') <= 0 then
Exit;
// Okunabilir, blok başına bir nesne, nesne akışlarında hiçbir şey gizli değil
Pdf.SaveLoadedDocumentDiagnostic('invoice-diagnostic.pdf');
finally
Pdf.Free;
end;
end;
Düzenleme Dosyayı Neden Bozar ve Ne Yeniden Oluşturulmalıdır?
Bir PDF'de bayt konumlarını veya bayt sayılarını kodlayan üç şey vardır. Çapraz referans tablosu her nesne numarasını bir bayt ofsetine eşler. Dosyanın sonundaki startxref değeri tabloyu işaret eder. Ve her akış sözlüğü, akış gövdesinin kaç bayt kapladığını söyleyen bir /Length taşır
Dosyanın sonundan önce herhangi bir yerde bir karakteri değiştirin, ondan sonraki ofsetler yanlış olur. Bir içerik akışına bir satır ekleyin, onun /Length değeri de yanlış olur. Çoğu görüntüleyici dosyayı reddeder ve onu kurtaranlar bunu tarama yaparak yapar; bu da hatayı düzeltmek yerine gizler. Onarım, bu üçünü de baytların şu anda gerçekte söylediklerinden yeniden oluşturur
var
Options: THPDFDiagnosticRepairOptions;
Report: THPDFDiagnosticRepairReport;
begin
Options := THPDFDiagnosticRepairOptions.Default;
Options.VerifyOutput := True; // değiştirmeden önce sonucu yükle
if THotPDF.RepairDiagnosticDocument('invoice-diagnostic.pdf',
'invoice-fixed.pdf', Options, Report) then
Writeln(Format('%d objects, %d streams, %d lengths corrected, ' +
'%d xref rows rebuilt, %d pages verified',
[Report.ObjectCount, Report.StreamCount,
Report.RepairedStreamLengthCount, Report.RebuiltXRefEntryCount,
Report.VerifiedPageCount]))
else
Writeln(Format('repair failed (%d): %s',
[Ord(Report.Status), string(Report.Diagnostic)]));
end;
Baytları Kopyalayın, Yeniden Seri Hale Getirmeyin
Bu aracı güvenilir kılan tasarım kararı, belgeyi hiçbir zaman yükleyip geri yazmamasıdır. Doğruladığı nesnelerin bayt aralıklarını kopyalar, yalnızca yanlış olan /Length değerlerini değiştirir ve tabloyu, treyleri ve startxref'i bunların etrafında yeniden oluşturur
Yükleyip yeniden seri hale getirmek uygulamak çok daha kolay olurdu ve sessizce şeyleri değiştirirdi. Bilinmeyen nesne sözdizimi normalize edilir, dize kaçış dizileri yazıcının tercih ettiği biçimde yeniden yazılır ve zaten kodlanmış akış yükleri yeniden kodlanabilirdi. Bir hata ayıklama aracı için bu kabul edilemez: bir sayıyı düzenlediniz ve diff bin adet tesadüfi biçimlendirme değişikliği değil, bir sayı göstermelidir. İki dosya arasında tam olarak neyin değiştiğini bilmek istiyorsanız bu, iki PDF dosyasını yapı ve piksel bazında karşılaştırma başlığında ele alınan bir karşılaştırma sorunudur
Sahte Nesneleri Önleyen İki Ayrıştırma Kuralı
Bir bayt aralığı tarayıcısı bariz bir tuzakla karşı karşıyadır: bir nesne başlığına benzeyen metin, bir akış yükünün veya bir dizenin içinde görünebilir. Naif bir tarama, bir içerik akışının ortasını işaret eden bir çapraz referans satırı üretir ve sonuçtaki dosya yeni ve daha kafa karıştırıcı bir şekilde bozuk olurdu
HotPDF, doğrulanmış her nesnenin kaydedilen bitiş ofsetini kullanarak tüm bayt aralığını atlayarak bunu önler, bu yüzden bir nesne gövdesinin içindeki hiçbir şey aday olarak değerlendirilmez. Nesneler arasında yalnızca PDF boşluk karakterlerine ve yorumlara izin verilir; başka her şey, bölgenin anlaşılmadığı ve baytlarının çıktıya çekilmemesi gerektiği anlamına gelir
Akış uzunlukları da eşit özen gerektirir. Gerçek yük uzunluğu, bir yazıcının endstream'den önce eklediği satır sonu sınırlayıcısını hariç tutar. Bildirilen uzunluk tam olarak işaretçiye denk geldiğinde bu bildirim kabul edilir. Denk gelmediğinde onarıcı, endstream ve endobj çifti için sınırlı bir arama yapar ve tam olarak bir sınırlayıcıyı, bir CR, bir LF veya bir CRLF'yi çıkarır. Bunu bir bayt yanlış yapmak, açılan ve içerik akışının sonunda başıboş bir operatör bulunan bir sayfayı render eden bir dosya üretir
Treylerin Saklamasına İzin Verilenler
Yeniden oluşturulan treyler eskisinin bir kopyası değildir. /Size, /Prev ve /XRefStm hepsi önceki dosya düzenini tanımlar ve yeniden hesaplanır veya bırakılır. Yalnızca hedefleri doğrulanmış girdiler hayatta kalır: /Info, /ID ve /Encrypt. Ve /Root, tam olarak bir Catalog nesnesine çözümlenmelidir — sıfır değil, birkaç tane de değil; bu da nesne bloklarının kopyala-yapıştır yoluyla bir araya getirilmesiyle oluşturulan bir dosyanın üretme eğiliminde olduğu şeydir
Çıktı güvenliği, insanların önemsediği dosyalara karşı çalışan bir araç için olması gerektiği gibi ele alınır. Sonuç, hedef dizinde geçici bir dosyaya yazılır, ardından çapraz referans kurtarma devre dışı bırakılmış normal yol üzerinden yüklenerek doğrulanır, bu yüzden yalnızca kurtarma sayesinde açılan bir dosya başarısızlık sayılır. Sayfa ağacı doğrulandıktan sonra ancak o zaman geçici dosya hedefin yerini atomik olarak alır. Başarısız bir onarım hiçbir zaman mevcut bir çıktının üzerine yazmaz
Bütçeler ve Dürüst Başarısızlık Kodları
Üç sınır işi sınırlar: giriş baytları, aday nesne sayısı ve varsayılan olarak 8 GiB, iki milyon ve iki milyon olan maksimum nesne numarası. Nesne numarası üst sınırı göründüğünden daha önemlidir, çünkü milyarlarca numaralandırılmış birkaç nesneye sahip seyrek bir tablo, aksi halde yeniden oluşturulan çapraz referans tablosunu muazzam şekilde şişirirdi. Klasik çapraz referans tabloları ayrıca on ondalık basamaktan fazlasına ihtiyaç duyacak ofsetleri reddeder; bu bir uygulama tercihi değil bir biçim sınırıdır
Başarısızlıklar bir boolean yerine belirli bir durum bildirir: geçersiz argümanlar, kaynak çok büyük, tanılama dosyası değil, nesne sınırı aşıldı, geçersiz nesne, yinelenen nesne, eksik katalog, geçersiz treyler, çıktı hatası veya doğrulama başarısız. Her biri farklı bir düzeltmeye karşılık gelir. Yinelenen bir nesne, bir nesne bloğunu iki kez yapıştırdığınız anlamına gelir. Eksik bir katalog genellikle /Type /Catalog tutan nesnenin hasar gördüğü anlamına gelir. Doğrulama başarısız, yapının artık tutarlı olduğu ama sayfa ağacının yüklenmediği anlamına gelir; bu genellikle /Count'uyla uyumsuz şekilde düzenlenmiş bir /Kids dizisidir
İki pratik not döngüyü kapatır. Yalnızca onarılmış olanı değil, tanılama dosyasını da saklayın; böylece bir sonraki düzenleme okunabilir bir temelden başlar. Ve tanılama çıktısını son kullanıcılara göndermeyin: hiçbir şey nesne akışlarına sıkıştırılmadığı için normal bir kayıttan daha büyüktür ve kompakt bir dosya için üretim yolu, nesne akışları ve artımlı güncellemeler başlığında anlatılan sıradan kayıt yoludur. Amaç bir şeyi değiştirmek değil neyin yanlış olduğunu bulmaksa, preflight rapor otomasyonu başlığındaki otomatik yol, baytları okumaktan daha hızlı yanıt verir
Tanılama kaydı, onarım, preflight ve karşılaştırma, Delphi ve C++Builder'da aynı yüklenmiş belge modeli üzerinde çalışır; eksiksiz özellik listesi HotPDF Delphi PDF bileşeni sayfasında bulunur