تخطَّ إلى المحتوى
getnextpdf.com

Pro الإصدار

Diff — مرجع متعمّق

هذه الصفحة هي المرجع على مستوى العقد لوحدة ⁨diff⁩ في ⁨NextPDF Pro⁩، وهي NextPDF\Pro\Diff. تقارن هذه الوحدة مستندَي ⁨PDF⁩ وتُبلّغ عن تغييرات النص والصور والبيانات الوصفية. ينتج PdfDiffer مقارنة أسطر بخوارزمية ⁨Myers⁩ مُحاذاة على مستوى الصفحات. يضيف StructuredDiffer تجميع الفقرات ومقارنة الصور ومقارنة البيانات الوصفية. يُسلسِل DiffFormatter النتيجة المُهيكلة إلى ⁨JSON⁩ أو جزء ⁨HTML⁩. تُبيّن هذه الصفحة واجهة برمجة التطبيقات العامة، وعقد السلوك القابل للملاحظة، وحدود الموارد، وأنماط الإخفاق. يوجد الإعداد الموجّه للمهام والعيّنات في صفحة قدرة ⁨Diff⁩.

تُشحن هذه القدرة ضمن ⁨NextPDF Pro⁩ (nextpdf/pro) وتُفعَّل بمظروف ترخيص من فئة ⁨Pro⁩. لا يُحمِّل أي نشر يفتقر إلى ذلك الاستحقاق أصنافَ هذه القدرة. قارن بين الإصدارات واحصل على ترخيص.

لا توجد راية قدرة زمن التشغيل تحجب هذه الوحدة. أصناف ⁨diff⁩ قابلة للاستخدام متى ما كان nextpdf/pro مُثبَّتًا ومُرخَّصًا.

سطح واجهة برمجة التطبيقات العامة

قسم بعنوان «سطح واجهة برمجة التطبيقات العامة»
الرمزالمعامِلاتالسلوك الافتراضيالقيمة المُعادةيرمي أو يُخفق بـملاحظات
PdfDiffer::compare()string $sourcePdf, string $targetPdfيستخرج نص كل صفحة، ثم يقارن الصفحة i من المصدر بالصفحة i من الهدفDiffResultInvalidArgumentException عندما يفتقر مخزن مؤقت إلى ترويسة %PDF أو يُخفق القارئ الاختياري في التحليل؛ OverflowException عند بلوغ حد موردنقطة دخول ساكنة (static)
PdfDiffer::compareTexts()array $sourcePages, array $targetPages (list<string> لكلٍّ منهما)يقارن نصوص الصفحات المُستخرَجة مسبقًا، متجاوزًا الاستخراجDiffResultOverflowException عند بلوغ حد موردساكنة؛ استخدمها عندما يكون النص متوفّرًا بالفعل
PdfDiffer::extractText()string $contentStreamيحلّل مُعامِلات إظهار النص من مجرى محتوى خام واحدstring— (متسامح مع الأخطاء؛ المُدخل غير القابل للتحليل يُنتج سلسلة فارغة)ساكنة
StructuredDiffer::__construct()?ImageDiffer $imageDiffer = null, ?MetadataDiffer $metadataDiffer = nullالوسائط null تُنشئ المقارِنات الافتراضيةحقن عبر المُنشئ لأغراض الاختبار
StructuredDiffer::compare()string $sourcePdf, string $targetPdfيُجري مقارنة النص والفقرات والصور والبيانات الوصفية، ثم يبني ملخّصًاStructuredDiffResultيُمرِّر InvalidArgumentException وOverflowException من مسار النصالمنسّق عبر الوحدة بأكملها
DiffFormatter::toJson()StructuredDiffResult $resultمستند JSON منسّق للطباعةstringJsonException عند إخفاق الترميز
DiffFormatter::toHtml()StructuredDiffResult $resultجزء HTML يضم أقسام الملخّص والفقرات والبيانات الوصفية؛ تُهرَّب قيم النص ككياناتstringجزء فقط، وليس مستندًا كاملًا
DiffFormatter::toArray()StructuredDiffResult $resultمصفوفة التسلسل التي يعتمد عليها toJson()array<string, mixed>مفاتيح snake_case ثابتة
ImageDiffer::diff()string $sourcePdf, string $targetPdfيُجزّئ (hash) كائنات الصور XObjects ويُبلّغ عن الصور المُضافة والمحذوفة والمعدّلةlist<ImageDiff>— (البنى غير القابلة لفكّ الترميز تُتجاوز على نحوٍ مُغلَق عند الإخفاق)الهوية هي دلو الصفحة إضافةً إلى رقم الكائن
MetadataDiffer::diff()string $sourcePdf, string $targetPdfيقارن ثمانية حقول /Info (Title, Author, Subject, Keywords, Creator, Producer, CreationDate, ModDate)list<MetadataChange>— (لا يرمي أبدًا عند مُدخل غير مطابق)تُقارَن القيم كسلاسل مفكوكة الترميز
DiffEngine::diff()array $sourceLines, array $targetLines, int $pageIndex = 0, int $maxLines = 10000مقارنة أسطر Myers على قائمتَي أسطرlist<DiffRegion>OverflowException عندما تتجاوز الأسطر المجمّعة $maxLines أو تتجاوز مسافة التحرير الحد المقيَّد بالذاكرةساكنة؛ مُنتِج المناطق لجميع مسارات النص
TextExtractor::fromContentStream()string $contentStreamيُرمِّز المجرى إلى وحدات ويُشغّل آلة حالة النصlist<TextBlock>ساكنة
TextExtractor::fromOperations()array $operations (list<ContentStreamOp>)يُشغّل آلة حالة النص على العمليات المُحلّلة مسبقًاlist<TextBlock>ساكنة
ContentStreamParser::parse()يأخذ المُنشئ string $dataيُرمِّز المُعامِلات والمعطيات إلى وحدات؛ يتخطى القواميس والتعليقات؛ متسامح مع الأخطاءlist<ContentStreamOp>تُتخطى البايتات غير المُتعرَّف عليها، ولا تكون قاتلة أبدًا
ContentStreamOpstring $operator, list<mixed> $operandsكائن قيمة عملية للقراءة فقط؛ isTextOp() يُصنّف المُعامِلات المتعلقة بالنص
DiffResultlist<DiffRegion> $regions, int $sourcePagesCount, int $targetPagesCountيوزّع المناطق في $added و$removed و$modified؛ يكشف isIdentical() وhasDifferences() وtotalChanges()للقراءة فقط؛ مناطق Unchanged تبقى في $regions فقط
StructuredDiffResultمقارنة النص، والفقرات، والصور، وتغييرات البيانات الوصفية، والملخّصنتيجة مُجمَّعة؛ hasDifferences() وisIdentical() تُفوِّضان إلى الملخّصللقراءة فقط
DiffSummaryأعداد لكل فئة إضافةً إلى أعداد الصفحاتhasDifferences() وtotalChanges() على أعداد النص والصور والبيانات الوصفيةللقراءة فقط
DiffRegionDiffType $type, string $text, int $pageIndex, int $lineIndex, ?string $counterpartText = nullتغيير واحد على مستوى السطر$counterpartText يبقى null في المحرك المُشحون
ParagraphDiffالنوع، والنص، وفهرس الصفحة، وسطر البداية/النهاية، والمناطقمناطق متتالية من النوع نفسه على صفحة واحدة؛ lineCount()للقراءة فقط
ImageDiffالنوع، وفهرس الصفحة، وتجزئة المصدر، وتجزئة الهدف، ومُعرّف الكائنمُدخل تغيير صورة واحدالتجزئات سلاسل فارغة في الجهة الغائبة
MetadataChangestring $field, ?string $sourceValue, ?string $targetValueتغيير حقل واحد؛ isAdded() وisRemoved() وisModified()null يعني أن الحقل غائب
TextBlockالنص، و⁨x⁩، و⁨y⁩، واسم الخط، وحجم الخط، وفهرس السطرشريحة نص مُستخرَجة واحدة بموضع تقريبيللقراءة فقط
DiffTypeتعداد: Added, Removed, Modified, Unchangedتصنيف تغيير مدعوم بسلسلة للنصراجع ملاحظة Modified في عقد السلوك
ImageDiffTypeتعداد: Added, Removed, Modified, Unchangedتصنيف تغيير مدعوم بسلسلة للصور
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() نص كل صفحة، ثم يقارن الصفحة ⁨i⁩ من المصدر بالصفحة ⁨i⁩ من الهدف. عندما تختلف أعداد الصفحات، تُعامَل الجهة الناقصة كنص فارغ للصفحات الزائدة. داخل كل زوج صفحات، يُقسَّم النص عند أسطر جديدة وتُشغَّل مقارنة أسطر ⁨Myers⁩ لكل صفحة. يُصدر المحرك مناطق Added وRemoved وUnchanged. يظهر السطر المُتغيّر كمنطقة Removed إضافةً إلى منطقة Added؛ ولا يُصدر المحرك المُشحون أبدًا مناطق نص Modified. تخدم حالة Modified ودلو DiffResult::$modified النتائج التي يبنيها المُستدعي، لأن مُنشئ DiffResult عام. يَعُدّ totalChanges() المناطق المُضافة والمحذوفة والمعدّلة؛ وتُستبعَد المناطق غير المتغيرة.

للاستخراج مساران:

  • قارئ ⁨Artisan⁩ الاختياري موجود. عندما يكون صنف NextPDF\Parser\PdfReader الاختياري مُثبَّتًا، تُقرأ مجاري محتوى الصفحات من خلاله للحصول على نص دقيق على مستوى الصفحة. يقود عددُ صفحات المُذيّل (⁨trailer⁩) الحلقةَ. الصفحة التي تُخفق قراءتها تُسهم بنص فارغ بدلًا من إجهاض المقارنة.
  • المسار الاحتياطي. يحدّد ماسحٌ مُقيَّد على مستوى البايت أزواج stream/endstream عبر strpos، ويفكّ ضغط بيانات ⁨FlateDecode⁩ بسقف إخراج صارم قدره ⁨50 MB⁩، ويعكس مرشّح مُتنبّئ ⁨PNG⁩ عندما يطلب قاموس المجرى ذلك عبر /DecodeParms وفق ⁨ISO 32000-2:2020 §7.4.4.4⁩. المُتنبّئ المُشوَّه أو غير المدعوم يترك البايتات المفكوكة دون تغيير. يُلحِق المسار الاحتياطي كل النص المُستعاد في دلو صفحة واحد، لذا فإن المحاذاة على مستوى الصفحة تكون دقيقة على مستوى الصفحة فقط في مسار القارئ.

يحلّل كلا المسارين مُعامِلات إظهار النص من ⁨§9.4⁩ وهي Tj وTJ و'. تتعقّب آلة الحالة BT/ET وTm (المنشأ فقط) وTd/TD وT* وTf.

يُجري StructuredDiffer::compare() مقارنة النص، ويجمّع المناطق المتتالية من النوع نفسه على الصفحة نفسها في فقرات (بما في ذلك التسلسلات غير المتغيرة)، ثم يُجري مقارنة الصور والبيانات الوصفية ويُجمِّع DiffSummary. تغطي أعداد فقرات الملخّص الفقرات المُضافة والمحذوفة والمعدّلة فقط.

تعدّ مقارنةُ الصور كائنات ⁨PDF⁩ بنيويًا. يُحكَم امتداد جسم المجرى بإدخال /Length الخاص به وفق ⁨§7.3.8.2⁩، لذا فإن البايتات الثنائية التي تشبه بنية الكائنات مجرد تشابه لا تُسجَّل أبدًا ككائنات وهمية. تُفكّ مجاري الكائنات المضغوطة (/Type /ObjStm) وفق ⁨§7.5.7⁩ كي تكون كائنات الصور ⁨XObjects⁩ المتداخلة داخلها ظاهرة. تُجزَّأ كل صورة مُكتشَفة بمحتواها باستخدام دالة xxh128 غير التشفيرية؛ والهوية هي زوج دلو الصفحة ورقم الكائن. تُنسَب الصور التي لا صفحة مالكة لها في ترتيب المجرى إلى الصفحة 0.

تحلّ مقارنةُ البيانات الوصفية قاموس /Info الحقيقي عبر المُذيّل عند الإمكان، بحيث لا يُخلَط بين رمز حقل خادع داخل مجرى محتوى وبين البيانات الوصفية للمستند. تُفكّ قيم الحقول كسلاسل ⁨PDF⁩: الصيغة الحرفية وفق ⁨§7.3.4.2⁩ والصيغة الست عشرية وفق ⁨§7.3.4.3⁩. بدون مُذيّل قابل للحل، يرجع البحث إلى المُدخل بأكمله. تُقارَن التواريخ كسلاسل مفكوكة الترميز، لا كطوابع زمنية مُحلّلة.

يُعيد DiffFormatter::toJson() نصَّ ⁨JSON⁩ منسّقًا للطباعة ويُرمِّز باستخدام JSON_THROW_ON_ERROR، بحيث يرفع إخفاقُ الترميز JsonException بدلًا من إعادة false. يُعيد toHtml() جزءًا من نوع <div class="nextpdf-diff">؛ ويمرّ نص الفقرات وقيم البيانات الوصفية عبر تهريب كيانات ⁨HTML⁩. لا يوجد إخراج ⁨PDF⁩ مرئي لمقارنة جنبًا إلى جنب بخط أحمر. بالنسبة إلى المُدخلات المتطابقة، تكون المناطق والمخرجات المنسّقة حتمية.

الحالات الحدّية وأنماط الإخفاق

قسم بعنوان «الحالات الحدّية وأنماط الإخفاق»
  • محاذاة الصفحات موضعية. صفحة واحدة مُدرَجة أو محذوفة تُزيح المحاذاة لجميع الصفحات اللاحقة وتُضخّم أعداد التغييرات اللاحقة.
  • في مسار الاستخراج الاحتياطي، يقع كل النص على فهرس الصفحة 0. مقارنة مستند مُستخرَج بالقارئ مع توقعات من المسار الاحتياطي تُنتج نسبة صفحات مختلفة.
  • المخزن المؤقت للمصدر أو الهدف الذي لا يبدأ بـ %PDF يُخفق بـ InvalidArgumentException قبل أي مقارنة.
  • أكثر من 10,000 سطر مجمّع في زوج صفحات واحد يُخفق بـ OverflowException (حد عدد الأسطر).
  • نصّا صفحتين يتشاركان أسطرًا قليلة جدًا يُخفقان بـ OverflowException بمجرد أن تتجاوز مسافة تحرير ⁨Myers⁩ الحد المقيَّد بالذاكرة. المراجعات المشروعة تتشارك معظم الأسطر وتبقى غير متأثرة؛ أما المُدخلات العدائية منخفضة التشارك فتُطلق الحد.
  • إخراج المجرى الاحتياطي بعد فك الضغط الأكبر من ⁨50 MB⁩ يُخفق بـ OverflowException (حد قنبلة فك الضغط). يستخدم الماسح strpos، لا تعبيرًا نمطيًا غير مُقيَّد، لذا لا يمكن لمُدخل مُصمَّم أن يُطلق تراجعًا كارثيًا.
  • مُعامِل إظهار النص " يُرمَّز إلى وحدة لكنه لا يُنتج أي كتلة نص في ⁨3.1.0⁩؛ والنص المُظهَر عبر " وحده لا يشارك في المقارنة.
  • ملفات ⁨PDF⁩ الممسوحة ضوئيًا والمكوّنة من صور فقط تُنتج مقارنة نص قليلة أو معدومة. لا يعمل أي ⁨OCR⁩.
  • كشف تغيير الصور بنيوي، لا إدراكي. فهو لا يُنقّط الصفحات، والصورة المُعاد ترميزها ببكسلات متطابقة تُبلَّغ كمعدّلة عندما تختلف بايتاتها.
  • الصورة التي يتغيّر دلو صفحتها أو رقم كائنها بين المراجعات تُبلَّغ كزوج محذوف-مضاف، لا كمعدّلة.
  • مجاري الكائنات المضغوطة بمرشّحات غير ⁨FlateDecode⁩ تُتجاوز على نحوٍ مُغلَق عند الإخفاق؛ ولا تُقارَن صورها الأعضاء.
  • لا تحدث أي عملية تشفيرية في هذه الوحدة، لذا لا يوجد سلوك خاص بوضع ⁨FIPS⁩. تجزئة الصورة لكشف التغيير فقط ولا تحمل أي وزن نزاهة أو إثبات.
الادّعاءالمعيارالبند
يُحلَّل مُعامِلا إظهار النص Tj وTJ لأغراض الاستخراجISO 32000-2:2020§9.4
تبدأ بيانات المجرى الاحتياطي بعد CRLF أو LF الذي يلي الكلمة المفتاحية streamISO 32000-2:2020§7.3.8.1
امتدادات مجرى مسح الصور يُحكَم بها بإدخال القاموس /LengthISO 32000-2:2020§7.3.8.2
تُحدَّد أعضاء مجرى الكائنات عبر جدول أزواج /N وإزاحة /FirstISO 32000-2:2020§7.5.7
يتبع عكسُ مُتنبّئ PNG معامِل Predictor في /DecodeParmsISO 32000-2:2020§7.4.4.4
تفكّ قيمُ البيانات الوصفية صيغتَي السلسلة الحرفية والست عشريةISO 32000-2:2020§7.3.4.2, §7.3.4.3
إخراج PDF مرئي لمقارنة جنبًا إلى جنب بخط أحمرغير مدعوم (JSON/HTML فقط)

جميع البنود مُعاد صياغتها؛ ولا تُعيد ⁨NextPDF⁩ إنتاج النص المعياري. هذه بيانات قدرة، لا شهادات؛ ولا تحمل ⁨NextPDF⁩ أي شهادة ولا تمنح أيًّا منها. يُعيد استرجاعُ النص بناءَ نص الأسطر من مُعامِلات إظهار النص. وهو لا يُشغّل آلة حالة النص الكاملة في ⁨§9.4⁩، لذا فإن المقارنة على مستوى المحتوى، لا على مستوى الهندسة.

  • التوفّر ضمن حزمة ⁨Pro⁩: PdfDiffer وDiffEngine وTextExtractor وكائنات القيمة الخاصة بها منذ ⁨1.8.0⁩؛ وStructuredDiffer وDiffFormatter وImageDiffer وMetadataDiffer وكائناتها منذ 2.2.0. جميعها حالية في nextpdf/pro 3.1.0.
  • فضّل PdfDiffer::compareTexts() عندما يكون نص الصفحة متوفّرًا بالفعل؛ فهو يتخطى الاستخراج وأنماط إخفاقه بالكامل.
  • يُحسّن قارئ ⁨Artisan⁩ الاختياري دقة الاستخراج ونسبة الصفحات. يُكتشَف في زمن التشغيل ولا يُشترَط أبدًا.
  • التقط OverflowException عند مقارنة مُدخل غير موثوق؛ فالحدود رفض متعمَّد مُغلَق عند الإخفاق، لا أخطاء عابرة.
  • يُصدر DiffFormatter::toHtml() أسماء أصناف (diff-added وdiff-removed وdiff-modified وdiff-unchanged) لكن دون أي ورقة أنماط؛ وفّر ⁨CSS⁩ الخاص بك.
  • أنشئ StructuredDiffer بمقارِنات بديلة (⁨stub⁩) في الاختبارات لعزل مسار النص عن مسح الصور والبيانات الوصفية.

توثّق هذه الصفحة السلوك القابل للملاحظة خارجيًا وسطح واجهة برمجة التطبيقات العامة المدعوم فقط. مسارات أسماء النطاقات الداخلية، وأصناف المساعدة، وجداول الآليات، وأسماء ملفات كتيّب التشغيل، وبادئات التذاكر خارج النطاق.