Pro phiên bản
Diff — Tài liệu tham chiếu chuyên sâu
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”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.
Khả dụng & cấp phép
Phần tiêu đề “Khả dụng & cấp phép”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.
Bề mặt API công khai
Phần tiêu đề “Bề mặt API công khai”| Ký hiệu | Tham số | Hành vi mặc định | Trả về | Ném hoặc lỗi với | Ghi chú |
|---|---|---|---|---|---|
PdfDiffer::compare() | string $sourcePdf, string $targetPdf | 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 | DiffResult | InvalidArgumentException 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ất | DiffResult | OverflowException khi chạm giới hạn tài nguyên | Tĩnh; dùng khi văn bản đã sẵn có |
PdfDiffer::extractText() | string $contentStream | Phâ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 định | — | — | Tiêm qua constructor để phục vụ kiểm thử |
StructuredDiffer::compare() | string $sourcePdf, string $targetPdf | Chạ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ắt | StructuredDiffResult | Lan truyền InvalidArgumentException và OverflowException từ đường xử lý văn bản | Bộ điều phối trên toàn bộ module |
DiffFormatter::toJson() | StructuredDiffResult $result | Tài liệu JSON được in đẹp | string | JsonException 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 entity | string | — | Chỉ là đoạn, không phải một tài liệu hoàn chỉnh |
DiffFormatter::toArray() | StructuredDiffResult $result | Mả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 $targetPdf | Băm các image XObject và báo cáo ảnh được thêm, bị xóa và bị sửa đổi | list<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 $targetPdf | So 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 = 10000 | Myers line diff trên hai danh sách dòng | list<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 $contentStream | Token hóa stream và chạy máy trạng thái văn bản | list<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ẵn | list<TextBlock> | — | Tĩnh |
ContentStreamParser::parse() | constructor nhận string $data | Token hóa toán tử và toán hạng; bỏ qua dictionary và chú thích; dung sai lỗi | list<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 |
ContentStreamOp | string $operator, list<mixed> $operands | Value object thao tác readonly; isTextOp() phân loại các toán tử liên quan văn bản | — | — | — |
DiffResult | list<DiffRegion> $regions, int $sourcePagesCount, int $targetPagesCount | Phâ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 |
StructuredDiffResult | text diff, đoạn văn, hình ảnh, thay đổi siêu dữ liệu, tóm tắt | Kết quả tổng hợp; hasDifferences(), isIdentical() ủy quyền cho bản tóm tắt | — | — | Readonly |
DiffSummary | số đếm theo từng loại cộng số đếm trang | hasDifferences() và totalChanges() trên các số đếm văn bản, hình ảnh và siêu dữ liệu | — | — | Readonly |
DiffRegion | DiffType $type, string $text, int $pageIndex, int $lineIndex, ?string $counterpartText = null | Một thay đổi ở cấp dòng | — | — | $counterpartText giữ null trên engine được phát hành |
ParagraphDiff | loại, văn bản, chỉ số trang, dòng bắt đầu/kết thúc, các vùng | Các vùng cùng loại liên tiếp trên một trang; lineCount() | — | — | Readonly |
ImageDiff | loại, chỉ số trang, hash nguồn, hash đích, object id | Một mục thay đổi hình ảnh | — | — | Hash là chuỗi rỗng ở phía vắng mặt |
MetadataChange | string $field, ?string $sourceValue, ?string $targetValue | Một thay đổi trường; isAdded(), isRemoved(), isModified() | — | — | null nghĩa là trường vắng mặt |
TextBlock | văn bản, x, y, tên font, cỡ font, chỉ số dòng | Một text run trích xuất được với vị trí gần đúng | — | — | Readonly |
DiffType | enum: Added, Removed, Modified, Unchanged | Phân loại thay đổi hậu thuẫn bằng chuỗi cho văn bản | — | — | Xem ghi chú Modified trong hợp đồng hành vi |
ImageDiffType | enum: Added, Removed, Modified, Unchanged | Phân loại thay đổi hậu thuẫn bằng chuỗi cho hình ảnh | — | — | — |
Chữ ký điểm vào
Phần tiêu đề “Chữ ký điểm vào”public static function compare(string $sourcePdf, string $targetPdf): DiffResult
public static function compareTexts(array $sourcePages, array $targetPages): DiffResult
public static function extractText(string $contentStream): stringpublic function __construct( ?ImageDiffer $imageDiffer = null, ?MetadataDiffer $metadataDiffer = null,)
public function compare(string $sourcePdf, string $targetPdf): StructuredDiffResultpublic function toJson(StructuredDiffResult $result): string
public function toHtml(StructuredDiffResult $result): string
public function toArray(StructuredDiffResult $result): arraypublic static function diff( array $sourceLines, array $targetLines, int $pageIndex = 0, int $maxLines = self::MAX_DIFF_LINES,): arrayHợp đồng hành vi
Phần tiêu đề “Hợp đồng hành vi”Căn chỉnh trang và line diff
Phần tiêu đề “Căn chỉnh trang và line diff”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, Removed và Unchanged. 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ừ.
Các đường trích xuất
Phần tiêu đề “Các đường trích xuất”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/endstreambằngstrpos, 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/DecodeParmstheo 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 và '. Máy trạng thái theo dõi BT/ET, Tm (chỉ điểm gốc), Td/TD, T* và Tf.
So sánh có cấu trúc
Phần tiêu đề “So sánh có cấu trúc”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.
Đầu ra báo cáo
Phần tiêu đề “Đầu ra báo cáo”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.
Trường hợp biên & chế độ lỗi
Phần tiêu đề “Trường hợp biên & chế độ lỗi”- 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
%PDFsẽ thất bại vớiInvalidArgumentExceptiontrướ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
OverflowExceptionmộ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ùngstrpos, 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ứ.
Tính phù hợp
Phần tiêu đề “Tính phù hợp”| Tuyên bố | Tiêu chuẩn | Điều khoản |
|---|---|---|
Các toán tử hiển thị văn bản Tj và TJ được phân tích để trích xuất | ISO 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 stream | ISO 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 dictionary | ISO 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 /First | ISO 32000-2:2020 | §7.5.7 |
Việc đảo ngược PNG predictor tuân theo tham số Predictor trong /DecodeParms | ISO 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ân | ISO 32000-2:2020 | §7.3.4.2, §7.3.4.3 |
| Đầu ra PDF redline cạnh nhau trực quan | — | Khô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.
Ghi chú phát triển
Phần tiêu đề “Ghi chú phát triển”- Khả dụng trong gói Pro:
PdfDiffer,DiffEngine,TextExtractorvà các value object của chúng từ 1.8.0;StructuredDiffer,DiffFormatter,ImageDiffer,MetadataDiffervà của chúng từ 2.2.0. Tất cả đều hiện hành trongnextpdf/pro3.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
OverflowExceptionkhi 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
StructuredDiffervớ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.
Ranh giới công bố
Phần tiêu đề “Ranh giới công bố”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.
Xem thêm
Phần tiêu đề “Xem thêm”- Diff (năng lực) — cài đặt, hướng dẫn nhanh và các ví dụ mẫu production.
- Converter — Tài liệu tham chiếu chuyên sâu
- Filter — Tài liệu tham chiếu chuyên sâu