مقارنة مستندات Word C# باستخدام مقارنة التدفق في .NET
مقدمة
إذا كنت بحاجة إلى compare word documents c# في تطبيق .NET مع الحفاظ على استهلاك الذاكرة منخفضًا، فأنت في المكان الصحيح. المقارنة التقليدية القائمة على الملفات تجبر المستند بالكامل على الذاكرة، مما يصبح عنق زجاجة سريعًا للملفات الكبيرة أو السيناريوهات السحابية التي لا يتوفر فيها سوى تدفق. يوضح هذا الدليل، خطوة بخطوة، كيفية إجراء مقارنة مستندات مستندة إلى التدفق باستخدام GroupDocs.Comparison، مع أمثلة واقعية، نصائح أداء، وإرشادات استكشاف الأخطاء.
إجابات سريعة
- ما المكتبة التي تتعامل مع مقارنة التدفق؟ GroupDocs.Comparison لـ .NET.
- هل يمكنني مقارنة ملفات Word مباشرةً من MemoryStream؟ نعم – فقط مرّر التدفق إلى المقارن.
- هل أحتاج إلى ترخيص للإنتاج؟ بالتأكيد؛ ترخيص GroupDocs.Comparison صالح يزيل العلامات المائية.
- ما إصدارات .NET المدعومة؟ .NET Framework 4.6.1+، .NET Core 2.0+، .NET 5/6/7.
- هل الدعم غير المتزامن مدمج؟ ليس أصلاً، لكن يمكنك تغليف الاستدعاءات في
Task.Runللحصول على سلوك غير متزامن أساسي.
ما هي مقارنة المستندات المستندة إلى التدفق؟
فئة Comparer في GroupDocs.Comparison تقرأ بيانات المستند من أي تنفيذ لـ Stream، مما يتيح المقارنة دون الحاجة لكتابة الملف على القرص. هذا يجعلها مثالية للتخزين السحابي، معالجة الملفات الكبيرة، وخدمات الويب ذات التزامن العالي.
لماذا نستخدم مقارنة مستندة إلى التدفق لمقارنة مستندات Word C#؟
تقليل ضغط الذاكرة يتم عبر معالجة البيانات على دفعات بدلاً من تحميل الملف بالكامل. يدعم GroupDocs.Comparison أكثر من 50 تنسيقًا للمدخلات والإخراج—بما في ذلك DOCX، PDF، PPTX، وXLSX—ويمكنه التعامل مع مستندات مئات الصفحات دون استنزاف RAM الخادم. النهج يتماشى أيضًا مع Azure Blob، AWS S3، أو أي تخزين HTTP حيث تستقبل Stream بدلاً من مسار ملف فعلي.
المتطلبات المسبقة
- GroupDocs.Comparison لـ .NET (الإصدار 25.4.0 أو أحدث) – يدعم أكثر من 50 تنسيقًا.
- .NET Framework 4.6.1+ أو .NET Core 2.0+ (بما في ذلك .NET 5/6/7).
- بيئة تطوير متكاملة تدعم C# (Visual Studio، VS Code، أو Rider).
- معرفة أساسية بتدفقات C# (
FileStream،MemoryStream) وعباراتusing.
إعداد GroupDocs.Comparison لـ .NET
خطوات التثبيت
باستخدام وحدة تحكم مدير الحزم NuGet
Install-Package GroupDocs.Comparison -Version 25.4.0
Install-Package GroupDocs.Comparison -Version 25.4.0
باستخدام .NET CLI
dotnet add package GroupDocs.Comparison --version 25.4.0
dotnet add package GroupDocs.Comparison --version 25.4.0
نصيحة احترافية: قم بتثبيت رقم الإصدار لتجنب التغييرات المفاجئة عند ظهور إصدار رئيسي جديد.
إعداد الترخيص (مهم!)
يتطلب GroupDocs.Comparison ترخيصًا للاستخدام في الإنتاج. يمكنك البدء بنسخة تجريبية مجانية، الحصول على ترخيص مؤقت لأعمال إثبات المفهوم، أو شراء ترخيص كامل للنشر غير المحدود. زر شراء GroupDocs للمزيد من التفاصيل.
تهيئة الترخيص الأساسي
var license = new GroupDocs.Comparison.License();
license.SetLicense("GroupDocs.Comparison.lic");
using GroupDocs.Comparison;
using System.IO;
// This is your foundation for all comparisons
Comparer comparer = new Comparer();
الآن أنت جاهز لمقارنة المستندات من أي مصدر تدفق.
كيف تقارن مستندات Word C# باستخدام التدفقات؟
حمّل ملفات Word المصدر والهدف كـ streams، مرّرها إلى Comparer، واكتب النتيجة إلى stream إخراج. التدفق الكامل موضح أدناه.
الخطوة 1: إعداد تدفقات المصدر والهدف والإخراج
using (var sourceStream = File.OpenRead("Original.docx"))
using (var targetStream = File.OpenRead("Revised.docx"))
using (var resultStream = File.Create("ComparisonResult.docx"))
{
// Comparison logic goes here
}
string sourceDocumentPath = Path.Combine("YOUR_DOCUMENT_DIRECTORY", "source.docx");
string targetDocumentPath = Path.Combine("YOUR_DOCUMENT_DIRECTORY", "target.docx");
string outputDirectory = Path.Combine("YOUR_OUTPUT_DIRECTORY", ".");
string outputFileName = Path.Combine(outputDirectory, "comparison_result.docx");
using (Comparer comparer = new Comparer(File.OpenRead(sourceDocumentPath)))
{
// Step 2: Add the Target Document
comparer.Add(File.OpenRead(targetDocumentPath));
// Step 3: Perform Comparison and Save Results
comparer.Compare(File.Create(outputFileName));
}
شرح:
File.OpenReadينشئ تدفقات قراءة فقط للملفين Word.File.Createيفتح تدفق كتابة فقط حيث سيتم حفظ نتيجة المقارنة.- عبارات
usingتضمن إغلاق كل تدفق بمجرد انتهاء الكتلة، مما يمنع قفل الملفات وتسرب الذاكرة.
الخطوة 2: تهيئة Comparer باستخدام تدفق المصدر
var comparer = new GroupDocs.Comparison.Comparer(sourceStream);
// Example: Comparing documents from byte arrays
byte[] sourceBytes = GetDocumentFromDatabase(sourceId);
byte[] targetBytes = GetDocumentFromDatabase(targetId);
using (var sourceStream = new MemoryStream(sourceBytes))
using (var targetStream = new MemoryStream(targetBytes))
using (var outputStream = new MemoryStream())
using (var comparer = new Comparer(sourceStream))
{
comparer.Add(targetStream);
comparer.Compare(outputStream);
// Now you can work with the result in memory
byte[] resultBytes = outputStream.ToArray();
}
مرساة التعريف: فئة Comparer هي المكوّن الأساسي في GroupDocs.Comparison الذي ينسق تحميل، تحليل، وإنشاء الفروقات بين تدفقات المستندين أو أكثر.
الخطوة 3: إضافة تدفق(ات) الهدف
comparer.Add(targetStream);
// If you must reuse a stream, reset its position
stream.Position = 0;
يمكنك استدعاء Add عدة مرات لمقارنة المصدر مع إصدارات هدف متعددة في تشغيل واحد.
الخطوة 4: تنفيذ المقارنة وكتابة النتيجة
ComparisonResult يمثل نتيجة المقارنة، يحتوي على مستند الفروقات والبيانات الوصفية المرتبطة.
var result = comparer.Compare();
result.Save(resultStream);
// Good - automatic disposal
using (var stream = File.OpenRead(path))
{
// Use stream
}
// Also good - manual disposal
var stream = File.OpenRead(path);
try
{
// Use stream
}
finally
{
stream?.Dispose();
}
ماذا يحدث هنا؟
Compare()يعالج كلا التدفقين، يكتشف الإدخالات، الحذف، وتغييرات التنسيق، ويعيد كائنComparisonResult.Save()يكتب مستند المقارنة المميز إلىresultStreamالذي أنشأته مسبقًا.
معالجة التدفق المتقدمة
العمل مع MemoryStream (مثل الملفات التي تم تحميلها عبر HTTP)
عند استلام تطبيقك لملف مرفوع، عادةً ما تحصل على MemoryStream. نفس الـ API يعمل دون تعديل:
var uploadedSource = new MemoryStream(await httpRequest.Form.Files[0].OpenReadStream().ReadAllBytesAsync());
var uploadedTarget = new MemoryStream(await httpRequest.Form.Files[1].OpenReadStream().ReadAllBytesAsync());
var comparer = new GroupDocs.Comparison.Comparer(uploadedSource);
comparer.Add(uploadedTarget);
var result = comparer.Compare();
await result.SaveAsync(response.Body);
if (stream.CanSeek)
{
// Safe to use Position and Length properties
}
لماذا هذا مهم: استخدام MemoryStream يلغي الحاجة إلى ملفات مؤقتة على القرص، مما يحسن الأداء في خدمات الويب غير الحالة والبيئات الحاوية.
المشكلات الشائعة والحلول
المشكلة #1: عدم إعادة تعيين موضع التدفق
المشكلة: إذا تم قراءة التدفق مسبقًا (مثلاً للتحقق)، قد يكون موضعه في النهاية، مما يجعل المقارن يقرأ صفر بايت.
الحل: أعد تعيين الموضع قبل تمرير التدفق:
sourceStream.Position = 0;
targetStream.Position = 0;
// Example of async file reading (though GroupDocs.Comparison doesn't support async yet)
var sourceBytes = await File.ReadAllBytesAsync(sourcePath);
using (var sourceStream = new MemoryStream(sourceBytes))
{
// Comparison logic
}
المشكلة #2: نسيان إغلاق التدفقات
المشكلة: التدفقات غير المغلقة تبقي مقابض الملفات مفتوحة، مما يسبب أخطاء “الملف قيد الاستخدام”.
الحل: احرص دائمًا على تغليف التدفقات بكتل using أو استدعاء Dispose() صراحةً، كما هو موضح في التنفيذ الأساسي.
المشكلة #3: استخدام تدفقات غير قابلة للبحث
المشكلة: بعض تدفقات الشبكة (مثل NetworkStream) لا تدعم البحث، وهو ما قد يتطلبه المقارن.
الحل: انسخ التدفق غير القابل للبحث إلى MemoryStream أولاً:
var seekableStream = new MemoryStream();
await nonSeekableStream.CopyToAsync(seekableStream);
seekableStream.Position = 0;
[HttpPost]
public async Task<IActionResult> CompareDocuments(IFormFile sourceFile, IFormFile targetFile)
{
using (var sourceStream = sourceFile.OpenReadStream())
using (var targetStream = targetFile.OpenReadStream())
using (var outputStream = new MemoryStream())
using (var comparer = new Comparer(sourceStream))
{
comparer.Add(targetStream);
comparer.Compare(outputStream);
return File(outputStream.ToArray(), "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "comparison.docx");
}
}
أفضل ممارسات الأداء
تحسين استخدام الذاكرة
- ضبط حجم المخزن المؤقت: للملفات الأكبر من 50 ميغابايت، زد حجم المخزن الداخلي إلى 1 ميغابايت لتقليل دورات القراءة‑الكتابة.
- I/O غير متزامن: في ASP.NET Core، استخدم واجهات ملفات غير متزامنة (
FileStream.OpenReadAsync) لتفريغ الخيوط أثناء عمليات الإدخال/الإخراج.
مراقبة استهلاك الموارد
- عدادات الأداء: تتبع
Process.PrivateMemorySize64قبل وبعد المقارنة للتحقق من تأثير الذاكرة. - الاختبار القياسي: نفّذ اختبارات
dotnet benchmarkللمقارنة بين النهجين القائمين على الملفات والتدفق؛ عادةً ما تكون عمليات التدفق أسرع بنسبة 20‑30 % على ملفات DOCX ذات 200 صفحة.
التحكم في التزامن
- نظام الطابور: حدّ عدد المقارنات المتزامنة إلى عدد نوى المعالج لتجنب تعطل الذاكرة.
- الإغلاق المبكر: حرّر تدفقات المصدر والهدف فور عودة
Compare()؛ يمكن إبقاء تدفق النتيجة مفتوحًا حتى كتابة النتيجة للعميل.
حالات الاستخدام الواقعية
الحالة 1: مراجعة مستندات تطبيق ويب
منصة SaaS تسمح للمستخدمين بتحميل نسختين من عقد للمراجعة الجانبية. تصل الملفات المرفوعة ككائنات IFormFile، تُحوَّل إلى MemoryStream وتُقارن فورًا، مع إرجاع DOCX قابل للتنزيل يحتوي على التغييرات المتتبعة.
الحالة 2: معالجة دفعة من التخزين السحابي
وظيفة Azure Function تُفعل عند إضافة blobs جديدة إلى حاوية، تقرأ كل blob كـ stream، تقارنه بالإصدار الأساسي المخزن في حاوية أخرى، وتكتب نتيجة المقارنة إلى حاوية “results”.
الحالة 3: تكامل نظام التحكم بالإصدار
خط أنابيب DevOps يستخرج ملفات Word من مستودع Git، يمررها كـ streams إلى GroupDocs.Comparison، وينتج تقرير فرق يُرفق بملف البناء للمراجعين.
دليل استكشاف الأخطاء وإصلاحها
| المشكلة | السبب المحتمل | الحل |
|---|---|---|
| “التدفق لا يدعم القراءة” | تم تمرير تدفق للكتابة فقط (مثل File.OpenWrite) | استخدم File.OpenRead أو تأكد من أن CanRead صحيح. |
| “المرجع إلى كائن غير موجود” | كان التدفق فارغًا أو مغلقًا قبل المقارنة | تحقق من تهيئة التدفق واحتفظ بكتلة using مفتوحة حتى بعد Compare(). |
| ضعف الأداء على ملفات >100 ميغابايت | حجم المخزن المؤقت الافتراضي صغير، أو مهام متزامنة كثيرة | زد حجم المخزن، حدّ التزامن، وقم بالتحليل باستخدام dotMemory. |
| أخطاء الترخيص في الإنتاج | ملف الترخيص مفقود أو المسار غير صحيح | ضع GroupDocs.Comparison.lic في جذر التطبيق واستدعِ SetLicense مبكرًا في بدء التشغيل. |
| بيانات التدفق تالفة | انقطاع الشبكة أثناء التحميل من التخزين السحابي | تحقق من طول التدفق والchecksum قبل المقارنة. |
خيارات التكوين المتقدمة
var options = new CompareOptions
{
HighlightColor = Color.Yellow,
ShowDeletedContent = true,
ShowInsertedContent = true,
StyleChangeDetection = true,
Password = "optionalPassword"
};
var comparer = new GroupDocs.Comparison.Comparer(sourceStream, options);
public async Task<byte[]> CompareCloudDocuments(string sourceUrl, string targetUrl)
{
using (var httpClient = new HttpClient())
using (var sourceStream = await httpClient.GetStreamAsync(sourceUrl))
using (var targetStream = await httpClient.GetStreamAsync(targetUrl))
using (var outputStream = new MemoryStream())
using (var comparer = new Comparer(sourceStream))
{
comparer.Add(targetStream);
comparer.Compare(outputStream);
return outputStream.ToArray();
}
}
مرساة التعريف: CompareOptions هو كائن تكوين يتيح لك التحكم في نمط العرض، الحماية بكلمة مرور، وأنواع التغييرات التي تُبلغ عنها.
التكامل مع أطر .NET الشائعة
تكامل ASP.NET Core
public async Task<IActionResult> Compare(IFormFile source, IFormFile target)
{
using var sourceStream = new MemoryStream();
using var targetStream = new MemoryStream();
await source.CopyToAsync(sourceStream);
await target.CopyToAsync(targetStream);
sourceStream.Position = 0;
targetStream.Position = 0;
var comparer = new GroupDocs.Comparison.Comparer(sourceStream);
comparer.Add(targetStream);
var result = comparer.Compare();
var output = new MemoryStream();
result.Save(output);
output.Position = 0;
return File(output, "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"ComparisonResult.docx");
}
public DocumentComparisonResult CompareDocumentVersions(int documentId, int version1, int version2)
{
var doc1Stream = GetDocumentVersionStream(documentId, version1);
var doc2Stream = GetDocumentVersionStream(documentId, version2);
using (doc1Stream)
using (doc2Stream)
using (var outputStream = new MemoryStream())
using (var comparer = new Comparer(doc1Stream))
{
comparer.Add(doc2Stream);
comparer.Compare(outputStream);
return new DocumentComparisonResult
{
ComparisonData = outputStream.ToArray(),
ComparedAt = DateTime.UtcNow,
SourceVersion = version1,
TargetVersion = version2
};
}
}
تكامل Windows Forms / WPF
var openFileDialog = new OpenFileDialog { Filter = "Word files (*.docx)|*.docx" };
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
using var source = File.OpenRead(openFileDialog.FileName);
// Repeat for target, then compare as shown earlier
}
using (var comparer = new Comparer(sourceStream))
{
comparer.Add(targetStream);
var compareOptions = new CompareOptions
{
ShowDeletedContent = true,
ShowInsertedContent = true,
GenerateSummaryPage = true
};
comparer.Compare(outputStream, compareOptions);
}
الخلاصة
مقارنة المستندات المستندة إلى التدفق في .NET توفر طريقة فعّالة في الذاكرة، جاهزة للسحابة، وعالية الأداء لمقارنة ملفات Word. باستخدام فئة Comparer من GroupDocs.Comparison، يمكنك العمل مباشرةً مع كائنات Stream، تجنّب الملفات المؤقتة، وتوسيع النطاق لآلاف المقارنات المتزامنة. اتبع أفضل الممارسات المذكورة أعلاه—الإغلاق السليم للتدفقات، ضبط المخزن، والترخيص—لضمان تنفيذ إنتاجي قوي.
الموارد
- شراء GroupDocs
- توثيق GroupDocs.Comparison
- مرجع API
- تحميل أحدث نسخة
- شراء ترخيص
- نسخة تجريبية مجانية
- ترخيص مؤقت
- دعم المجتمع
آخر تحديث: 2026-05-31
تم الاختبار مع: GroupDocs.Comparison 25.4.0 لـ .NET
المؤلف: GroupDocs
public class DocumentComparisonService
{
public async Task<ComparisonResult> CompareDocumentsAsync(Stream source, Stream target)
{
// Your comparison logic here
// This is where the earlier examples would fit
}
}
private void CompareButton_Click(object sender, EventArgs e)
{
using (var openFileDialog = new OpenFileDialog())
{
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
using (var stream = File.OpenRead(openFileDialog.FileName))
{
// Perform comparison
}
}
}
}