Bỏ qua để đến nội dung
getnextpdf.com

Pro phiên bản

Diff — Tài liệu tham chiếu chuyên sâu

Trang này là tài liệu tham chiếu cấp hợp đồng cho module diff của NextPDF Pro, NextPDF\Pro\Diff. Module so sánh hai tài liệu PDF và báo cáo các thay đổi về văn bản, hình ảnh và siêu dữ liệu. PdfDiffer tạo ra một Myers line diff căn chỉnh theo trang. StructuredDiffer bổ sung việc gom nhóm đoạn văn, so sánh hình ảnh và so sánh siêu dữ liệu. DiffFormatter tuần tự hóa kết quả có cấu trúc thành JSON hoặc một đoạn HTML. Trang này nêu rõ API công khai, hợp đồng hành vi quan sát được, các giới hạn tài nguyên và các chế độ lỗi. Phần thiết lập theo tác vụ và các ví dụ mẫu nằm trên trang năng lực Diff.

Năng lực này được phát hành trong NextPDF Pro (nextpdf/pro) và kích hoạt bằng một license envelope bậc Pro. Một triển khai không có quyền đó sẽ không nạp các lớp của năng lực này. So sánh các phiên bản và lấy giấy phép.

Không có cờ năng lực lúc chạy nào kiểm soát module này. Các lớp diff có thể dùng bất cứ khi nào nextpdf/pro được cài đặt và cấp phép.

Ký hiệuTham sốHành vi mặc địnhTrả vềNém hoặc lỗi vớiGhi chú
PdfDiffer::compare()string $sourcePdf, string $targetPdfTrích xuất văn bản theo từng trang, rồi so sánh trang i của nguồn với trang i của đíchDiffResultInvalidArgumentException khi một buffer thiếu header %PDF hoặc bộ đọc tùy chọn không phân tích được; OverflowException khi chạm giới hạn tài nguyênĐiểm vào tĩnh
PdfDiffer::compareTexts()array $sourcePages, array $targetPages (mỗi cái là list<string>)So sánh văn bản trang đã trích xuất sẵn, bỏ qua bước trích xuấtDiffResultOverflowException khi chạm giới hạn tài nguyênTĩnh; dùng khi văn bản đã sẵn có
PdfDiffer::extractText()string $contentStreamPhân tích các toán tử hiển thị văn bản từ một content stream thôstring— (dung sai lỗi; đầu vào không phân tích được trả về chuỗi rỗng)Tĩnh
StructuredDiffer::__construct()?ImageDiffer $imageDiffer = null, ?MetadataDiffer $metadataDiffer = nullĐối số null sẽ dựng các differ mặc địnhTiêm qua constructor để phục vụ kiểm thử
StructuredDiffer::compare()string $sourcePdf, string $targetPdfChạy so sánh văn bản, đoạn văn, hình ảnh và siêu dữ liệu, rồi dựng một bản tóm tắtStructuredDiffResultLan truyền InvalidArgumentExceptionOverflowException từ đường xử lý văn bảnBộ điều phối trên toàn bộ module
DiffFormatter::toJson()StructuredDiffResult $resultTài liệu JSON được in đẹpstringJsonException khi mã hóa thất bại
DiffFormatter::toHtml()StructuredDiffResult $resultĐoạn HTML gồm các phần tóm tắt, đoạn văn và siêu dữ liệu; các giá trị văn bản được escape entitystringChỉ là đoạn, không phải một tài liệu hoàn chỉnh
DiffFormatter::toArray()StructuredDiffResult $resultMảng tuần tự hóa làm nền cho toJson()array<string, mixed>Khóa snake_case ổn định
ImageDiffer::diff()string $sourcePdf, string $targetPdfBăm các image XObject và báo cáo ảnh được thêm, bị xóa và bị sửa đổilist<ImageDiff>— (các cấu trúc không giải mã được sẽ bị bỏ qua theo kiểu fail-closed)Danh tính là bucket trang cộng số hiệu đối tượng
MetadataDiffer::diff()string $sourcePdf, string $targetPdfSo sánh tám trường /Info (Title, Author, Subject, Keywords, Creator, Producer, CreationDate, ModDate)list<MetadataChange>— (không bao giờ ném với đầu vào không tuân thủ)Các giá trị được so sánh dưới dạng chuỗi đã giải mã
DiffEngine::diff()array $sourceLines, array $targetLines, int $pageIndex = 0, int $maxLines = 10000Myers line diff trên hai danh sách dònglist<DiffRegion>OverflowException khi tổng số dòng vượt $maxLines hoặc khoảng cách chỉnh sửa vượt mức trần giới hạn bộ nhớTĩnh; bộ tạo vùng cho mọi đường xử lý văn bản
TextExtractor::fromContentStream()string $contentStreamToken hóa stream và chạy máy trạng thái văn bảnlist<TextBlock>Tĩnh
TextExtractor::fromOperations()array $operations (list<ContentStreamOp>)Chạy máy trạng thái văn bản trên các thao tác đã phân tích sẵnlist<TextBlock>Tĩnh
ContentStreamParser::parse()constructor nhận string $dataToken hóa toán tử và toán hạng; bỏ qua dictionary và chú thích; dung sai lỗilist<ContentStreamOp>Byte không nhận diện được sẽ bị bỏ qua, không bao giờ gây lỗi nghiêm trọng
ContentStreamOpstring $operator, list<mixed> $operandsValue object thao tác readonly; isTextOp() phân loại các toán tử liên quan văn bản
DiffResultlist<DiffRegion> $regions, int $sourcePagesCount, int $targetPagesCountPhân các vùng vào $added, $removed, $modified; cung cấp isIdentical(), hasDifferences(), totalChanges()Readonly; các vùng Unchanged chỉ nằm trong $regions
StructuredDiffResulttext diff, đoạn văn, hình ảnh, thay đổi siêu dữ liệu, tóm tắtKết quả tổng hợp; hasDifferences(), isIdentical() ủy quyền cho bản tóm tắtReadonly
DiffSummarysố đếm theo từng loại cộng số đếm tranghasDifferences()totalChanges() trên các số đếm văn bản, hình ảnh và siêu dữ liệuReadonly
DiffRegionDiffType $type, string $text, int $pageIndex, int $lineIndex, ?string $counterpartText = nullMột thay đổi ở cấp dòng$counterpartText giữ null trên engine được phát hành
ParagraphDiffloại, văn bản, chỉ số trang, dòng bắt đầu/kết thúc, các vùngCác vùng cùng loại liên tiếp trên một trang; lineCount()Readonly
ImageDiffloại, chỉ số trang, hash nguồn, hash đích, object idMột mục thay đổi hình ảnhHash là chuỗi rỗng ở phía vắng mặt
MetadataChangestring $field, ?string $sourceValue, ?string $targetValueMột thay đổi trường; isAdded(), isRemoved(), isModified()null nghĩa là trường vắng mặt
TextBlockvăn bản, x, y, tên font, cỡ font, chỉ số dòngMột text run trích xuất được với vị trí gần đúngReadonly
DiffTypeenum: Added, Removed, Modified, UnchangedPhân loại thay đổi hậu thuẫn bằng chuỗi cho văn bảnXem ghi chú Modified trong hợp đồng hành vi
ImageDiffTypeenum: Added, Removed, Modified, UnchangedPhân loại thay đổi hậu thuẫn bằng chuỗi cho hình ảnh
public static function compare(string $sourcePdf, string $targetPdf): DiffResult
public static function compareTexts(array $sourcePages, array $targetPages): DiffResult
public static function extractText(string $contentStream): string
public function __construct(
?ImageDiffer $imageDiffer = null,
?MetadataDiffer $metadataDiffer = null,
)
public function compare(string $sourcePdf, string $targetPdf): StructuredDiffResult
public function toJson(StructuredDiffResult $result): string
public function toHtml(StructuredDiffResult $result): string
public function toArray(StructuredDiffResult $result): array
public static function diff(
array $sourceLines,
array $targetLines,
int $pageIndex = 0,
int $maxLines = self::MAX_DIFF_LINES,
): array

PdfDiffer::compare() trích xuất văn bản theo từng trang, rồi so sánh trang i của nguồn với trang i của đích. Khi số trang khác nhau, phía thiếu được coi là văn bản rỗng cho những trang dôi ra. Trong mỗi cặp trang, văn bản được tách theo các ký tự xuống dòng và một Myers line diff chạy trên từng trang. Engine phát ra các vùng Added, RemovedUnchanged. Một dòng bị thay đổi hiện ra dưới dạng một vùng Removed cộng một vùng Added; engine được phát hành không bao giờ phát ra vùng văn bản Modified. Trường hợp Modified và bucket DiffResult::$modified phục vụ các kết quả do bên gọi tự dựng, vì constructor của DiffResult là công khai. totalChanges() đếm các vùng added, removed và modified; các vùng unchanged bị loại trừ.

Trích xuất có hai đường:

  • Bộ đọc Artisan tùy chọn hiện diện. Khi lớp tùy chọn NextPDF\Parser\PdfReader được cài đặt, các content stream của trang được đọc qua nó để có văn bản chính xác theo trang. Số trang trong trailer điều khiển vòng lặp. Một trang đọc thất bại sẽ đóng góp văn bản rỗng thay vì hủy bỏ toàn bộ phép so sánh.
  • Dự phòng. Một bộ quét cấp byte có giới hạn định vị các cặp stream/endstream bằng strpos, giải nén dữ liệu FlateDecode với mức trần đầu ra cứng 50 MB, và đảo ngược bộ lọc một PNG predictor khi stream dictionary yêu cầu qua /DecodeParms theo ISO 32000-2:2020 §7.4.4.4. Một predictor sai định dạng hoặc không được hỗ trợ sẽ giữ nguyên các byte đã giải mã. Đường dự phòng nối tất cả văn bản khôi phục được vào một bucket trang duy nhất, nên căn chỉnh cấp trang chỉ chính xác theo trang trên đường bộ đọc.

Cả hai đường đều phân tích các toán tử hiển thị văn bản §9.4 Tj, TJ'. Máy trạng thái theo dõi BT/ET, Tm (chỉ điểm gốc), Td/TD, T*Tf.

StructuredDiffer::compare() chạy diff văn bản, gom các vùng cùng loại liên tiếp trên cùng một trang thành các đoạn văn (kể cả các chuỗi unchanged), rồi chạy so sánh hình ảnh và siêu dữ liệu và lắp ráp một DiffSummary. Số đếm đoạn văn trong bản tóm tắt chỉ bao gồm các đoạn được thêm, bị xóa và bị sửa đổi.

So sánh hình ảnh liệt kê các đối tượng PDF một cách có cấu trúc. Phạm vi của một thân stream được điều chỉnh bởi mục /Length của nó theo §7.3.8.2, nên các byte nhị phân chỉ trông giống cú pháp đối tượng sẽ không bao giờ bị ghi nhận là đối tượng ma. Các object stream nén (/Type /ObjStm) được giải mã theo §7.5.7 để các image XObject lồng bên trong chúng hiện ra. Mỗi hình ảnh phát hiện được sẽ được băm nội dung bằng hàm phi mật mã xxh128; danh tính là cặp bucket trang và số hiệu đối tượng. Các hình ảnh không có trang sở hữu theo thứ tự stream được quy về trang 0.

So sánh siêu dữ liệu phân giải dictionary /Info thật thông qua trailer khi có thể, nên một field token mồi nhử bên trong content stream không bị nhầm là siêu dữ liệu tài liệu. Các giá trị trường được giải mã dưới dạng chuỗi PDF: dạng literal theo §7.3.4.2 và dạng thập lục phân theo §7.3.4.3. Không có trailer phân giải được, việc tìm kiếm lùi về toàn bộ đầu vào. Các ngày tháng được so sánh dưới dạng chuỗi đã giải mã, không phải timestamp đã phân tích.

DiffFormatter::toJson() trả về JSON được in đẹp và mã hóa với JSON_THROW_ON_ERROR, nên một lỗi mã hóa sẽ nâng JsonException thay vì trả về false. toHtml() trả về một đoạn <div class="nextpdf-diff">; văn bản đoạn văn và các giá trị siêu dữ liệu đi qua bước escape entity HTML. Không có đầu ra PDF redline cạnh nhau trực quan. Với các đầu vào giống hệt nhau, các vùng và đầu ra đã định dạng là tất định.

  • Căn chỉnh trang dựa trên vị trí. Một trang được chèn hoặc xóa đơn lẻ sẽ làm lệch căn chỉnh cho mọi trang tiếp theo và thổi phồng số đếm thay đổi ở hạ nguồn.
  • Trên đường trích xuất dự phòng, toàn bộ văn bản rơi vào chỉ số trang 0. So sánh một tài liệu trích xuất bằng bộ đọc với kỳ vọng từ đường dự phòng sẽ cho quy kết trang khác nhau.
  • Một buffer nguồn hoặc đích không bắt đầu bằng %PDF sẽ thất bại với InvalidArgumentException trước bất kỳ phép so sánh nào.
  • Hơn 10,000 dòng gộp trong một cặp trang sẽ thất bại với OverflowException (giới hạn số dòng).
  • Hai văn bản trang chia sẻ quá ít dòng chung sẽ thất bại với OverflowException một khi khoảng cách chỉnh sửa Myers vượt mức trần giới hạn bộ nhớ. Các bản chỉnh sửa hợp lệ chia sẻ hầu hết các dòng và không bị ảnh hưởng; các đầu vào độc hại ít điểm chung sẽ chạm giới hạn.
  • Đầu ra stream dự phòng sau giải nén lớn hơn 50 MB sẽ thất bại với OverflowException (giới hạn bom giải nén). Bộ quét dùng strpos, không phải regex không giới hạn, nên đầu vào được dàn dựng không thể kích hoạt backtracking thảm họa.
  • Toán tử hiển thị văn bản " được token hóa nhưng không tạo ra text block nào trong 3.1.0; văn bản chỉ được hiển thị qua " sẽ không tham gia vào diff.
  • Các PDF quét, chỉ có hình ảnh sẽ tạo ra ít hoặc không có diff văn bản. Không có OCR nào chạy.
  • Phát hiện thay đổi hình ảnh mang tính cấu trúc, không phải tri giác. Nó không rasterize các trang, và một hình ảnh được mã hóa lại với các pixel giống hệt sẽ được báo là bị sửa đổi khi các byte của nó khác nhau.
  • Một hình ảnh có bucket trang hoặc số hiệu đối tượng thay đổi giữa các bản chỉnh sửa sẽ được báo là một cặp removed-cộng-added, chứ không phải modified.
  • Các object stream được nén bằng bộ lọc khác FlateDecode sẽ bị bỏ qua theo kiểu fail-closed; các hình ảnh thành viên của chúng không được so sánh.
  • Không có thao tác mật mã nào xảy ra trong module này, nên không tồn tại hành vi đặc thù chế độ FIPS. Hash hình ảnh chỉ dùng để phát hiện thay đổi và không mang trọng lượng toàn vẹn hay chứng cứ.
Tuyên bốTiêu chuẩnĐiều khoản
Các toán tử hiển thị văn bản TjTJ được phân tích để trích xuấtISO 32000-2:2020§9.4
Dữ liệu stream dự phòng bắt đầu sau CRLF hoặc LF theo sau từ khóa streamISO 32000-2:2020§7.3.8.1
Phạm vi stream khi quét ảnh được điều chỉnh bởi mục /Length của dictionaryISO 32000-2:2020§7.3.8.2
Các thành viên object-stream được định vị qua bảng cặp /N và offset /FirstISO 32000-2:2020§7.5.7
Việc đảo ngược PNG predictor tuân theo tham số Predictor trong /DecodeParmsISO 32000-2:2020§7.4.4.4
Các giá trị siêu dữ liệu giải mã dạng chuỗi literal và thập lục phânISO 32000-2:2020§7.3.4.2, §7.3.4.3
Đầu ra PDF redline cạnh nhau trực quanKhông hỗ trợ (chỉ JSON/HTML)

Tất cả các điều khoản đều được diễn giải lại; NextPDF không tái tạo văn bản quy phạm. Đây là các tuyên bố năng lực, không phải chứng nhận; NextPDF không nắm giữ chứng nhận nào và không cấp chứng nhận nào. Việc khôi phục văn bản dựng lại văn bản dòng từ các toán tử hiển thị văn bản. Nó không chạy toàn bộ máy trạng thái văn bản §9.4, nên phép so sánh ở cấp nội dung, không phải cấp hình học.

  • Khả dụng trong gói Pro: PdfDiffer, DiffEngine, TextExtractor và các value object của chúng từ 1.8.0; StructuredDiffer, DiffFormatter, ImageDiffer, MetadataDiffer và của chúng từ 2.2.0. Tất cả đều hiện hành trong nextpdf/pro 3.1.0.
  • Ưu tiên PdfDiffer::compareTexts() khi văn bản trang đã sẵn có; nó bỏ qua hoàn toàn bước trích xuất và các chế độ lỗi của bước đó.
  • Bộ đọc Artisan tùy chọn cải thiện độ chính xác trích xuất và quy kết trang. Nó được phát hiện lúc chạy và không bao giờ bắt buộc.
  • Bắt OverflowException khi so sánh đầu vào không tin cậy; các giới hạn là những sự từ chối fail-closed có chủ đích, không phải lỗi nhất thời.
  • DiffFormatter::toHtml() phát ra các tên lớp (diff-added, diff-removed, diff-modified, diff-unchanged) nhưng không có stylesheet; hãy tự cung cấp CSS của bạn.
  • Dựng StructuredDiffer với các differ stub trong kiểm thử để cô lập đường xử lý văn bản khỏi việc quét hình ảnh và siêu dữ liệu.

Trang này chỉ tài liệu hóa hành vi quan sát được từ bên ngoài và bề mặt API công khai được hỗ trợ. Các đường dẫn namespace nội bộ, lớp trợ giúp, bảng cơ chế, tên tệp runbook và tiền tố ticket nằm ngoài phạm vi.