Porovnat Word dokumenty C# pomocí porovnání proudu v .NET
Úvod
Pokud potřebujete compare word documents c# v .NET aplikaci a zároveň udržet nízkou spotřebu paměti, jste na správném místě. Tradiční porovnání založené na souborech načte celý dokument do RAM, což se rychle stane úzkým místem u velkých Word souborů nebo cloud‑native scénářů, kde máte k dispozici jen proud. Tento tutoriál vám krok za krokem ukáže, jak provést porovnání dokumentů založené na proudu pomocí GroupDocs.Comparison, včetně reálných příkladů, tipů na výkon a rad pro řešení problémů.
Rychlé odpovědi
- Která knihovna zpracovává porovnání proudu? GroupDocs.Comparison for .NET.
- Mohu porovnávat Word soubory přímo z MemoryStream? Yes – just pass the stream to the comparer.
- Potřebuji licenci pro produkci? Absolutely; a valid GroupDocs.Comparison license removes watermarks.
- Které verze .NET jsou podporovány? .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5/6/7.
- Je podpora async vestavěná? Not natively, but you can wrap calls in
Task.Runfor basic async behavior.
Co je porovnání dokumentů založené na proudu?
Třída Comparer v GroupDocs.Comparison čte data dokumentu z libovolné implementace Stream, což umožňuje porovnání bez nutnosti zapisovat soubor na disk. To ji činí ideální pro cloudové úložiště, zpracování velkých souborů a webové služby s vysokou souběžností.
Proč použít porovnání založené na proudu pro porovnání Word dokumentů C#?
Porovnání založené na proudu snižuje zatížení paměti tím, že data zpracovává po částech místo načítání celého souboru. GroupDocs.Comparison podporuje 50+ vstupních a výstupních formátů—včetně DOCX, PDF, PPTX a XLSX— a dokáže zpracovat dokumenty s několika stovkami stránek, aniž by vyčerpalo RAM serveru. Tento přístup také perfektně ladí s Azure Blob, AWS S3 nebo jakýmkoli úložištěm založeným na HTTP, kde získáte Stream místo fyzické cesty k souboru.
Předpoklady
- GroupDocs.Comparison for .NET (Version 25.4.0 nebo novější) – podporuje 50+ formátů.
- .NET Framework 4.6.1+ nebo .NET Core 2.0+ (včetně .NET 5/6/7).
- IDE s podporou C# (Visual Studio, VS Code nebo Rider).
- Základní znalost C# proudů (
FileStream,MemoryStream) ausingbloků.
Nastavení GroupDocs.Comparison pro .NET
Kroky instalace
Použití konzole správce balíčků NuGet
Install-Package GroupDocs.Comparison -Version 25.4.0
Install-Package GroupDocs.Comparison -Version 25.4.0
Použití .NET CLI
dotnet add package GroupDocs.Comparison --version 25.4.0
dotnet add package GroupDocs.Comparison --version 25.4.0
Tip: Připněte číslo verze, aby se předešlo neočekávaným breaking changes při vydání nové hlavní verze.
Nastavení licence (Důležité!)
GroupDocs.Comparison vyžaduje licenci pro produkční použití. Můžete začít s bezplatnou zkušební verzí, získat dočasnou licenci pro proof‑of‑concept práci, nebo zakoupit plnou licenci pro neomezené nasazení. Navštivte GroupDocs Purchase pro podrobnosti.
Základní inicializace licence
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();
Nyní jste připraveni porovnávat dokumenty z libovolného zdroje proudu.
Jak porovnat Word dokumenty C# pomocí proudů?
Načtěte své zdrojové a cílové Word soubory jako proudy, předávejte je Comparer a výsledek zapište do výstupního proudu. Kompletní tok je znázorněn níže.
Krok 1: Připravte zdrojové, cílové a výstupní proudy
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));
}
Vysvětlení:
File.OpenReadvytváří jen pro čtení proudy pro oba Word soubory.File.Createotevírá jen pro zápis proud, kam bude uložen výsledek porovnání.usingbloky zajišťují, že každý proud je uvolněn, jakmile blok skončí, což zabraňuje zamykání souborů a únikům paměti.
Krok 2: Inicializujte Comparer se zdrojovým proudem
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();
}
Definiční kotva: Třída Comparer je hlavní komponentou GroupDocs.Comparison, která orchestruje načítání, analýzu a generování rozdílů mezi dvěma nebo více dokumentovými proudy.
Krok 3: Přidejte cílový(é) proud(y)
comparer.Add(targetStream);
// If you must reuse a stream, reset its position
stream.Position = 0;
Můžete volat Add vícekrát pro porovnání zdroje s několika cílovými verzemi v jednom běhu.
Krok 4: Proveďte porovnání a zapište výsledek
ComparisonResult představuje výsledek porovnání, obsahuje dokument s rozdíly a související metadata.
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();
}
Co se zde děje?
Compare()zpracuje oba proudy, detekuje vložení, smazání a změny formátování a vrátí objektComparisonResult.Save()zapíše zvýrazněný dokument porovnání doresultStream, který jste vytvořili dříve.
Pokročilé zpracování proudů
Práce s MemoryStream (např. soubory nahrané přes HTTP)
Když vaše aplikace přijme nahrání souboru, typicky získáte MemoryStream. Stejná API funguje bez úprav:
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
}
Proč je to důležité: Použití MemoryStream eliminuje potřebu dočasných souborů na disku, což zlepšuje výkon ve stateless webových službách a kontejnerizovaných prostředích.
Časté úskalí a řešení
Úskalí #1: Pozice proudu není resetována
Problém: Pokud byl proud dříve čten (např. pro validaci), může být jeho pozice na konci, což způsobí, že comparer přečte nula bajtů.
Řešení: Resetujte pozici před předáním proudu:
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
}
Úskalí #2: Zapomenutí uvolnit proudy
Problém: Neuvolněné proudy drží otevřené souborové handly, což vede k chybám „soubor je používán“.
Řešení: Vždy zabalte proudy do using bloků nebo explicitně zavolejte Dispose(), jak je ukázáno v hlavní implementaci.
Úskalí #3: Použití ne‑seekovatelných proudů
Problém: Některé síťové proudy (např. NetworkStream) nepodporují seeking, což může comparer vyžadovat.
Řešení: Nejprve zkopírujte ne‑seekovatelný proud do 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");
}
}
Nejlepší postupy pro výkon
Optimalizace využití paměti
- Ladění velikosti bufferu: Pro dokumenty větší než 50 MB zvyšte interní velikost bufferu na 1 MB, aby se snížil počet čtení‑zápisů.
- Async I/O: V ASP.NET Core používejte asynchronní souborové API (
FileStream.OpenReadAsync) k uvolnění vláken během I/O.
Monitorování spotřeby zdrojů
- Performance Counters: Sledujte
Process.PrivateMemorySize64před a po porovnání pro ověření dopadu na paměť. - Benchmarking: Spusťte testy
dotnet benchmarkporovnávající přístupy založené na souborech a na proudu; typické běhy založené na proudu jsou o 20‑30 % rychlejší na 200‑stránkových DOCX souborech.
Řízení souběžnosti
- Systém front: Omezte současné porovnání na počet CPU jader, aby se předešlo pádům z nedostatku paměti.
- Uvolnit brzy: Uvolněte zdrojové a cílové proudy okamžitě po návratu
Compare(); výstupní proud může zůstat otevřený, dokud jej neodešlete klientovi.
Reálné příklady použití
Případ použití 1: Revize dokumentů ve webové aplikaci
SaaS platforma umožňuje uživatelům nahrát dvě verze smlouvy pro vedlejší revizi. Nahrané soubory přicházejí jako objekty IFormFile, které jsou převedeny na MemoryStream a okamžitě porovnány, přičemž vrací ke stažení DOCX s evidovanými změnami.
Případ použití 2: Dávkové zpracování z cloudového úložiště
Azure Function se spustí při nových blobech v kontejneru, načte každý blob jako proud, porovná jej s referenční verzí uloženou v jiném kontejneru a zapíše výsledek porovnání zpět do kontejneru „results“.
Případ použití 3: Integrace se systémem správy verzí
DevOps pipeline extrahuje Word soubory z Git repozitáře, streamuje je do GroupDocs.Comparison a generuje diff report, který je připojen k artefaktu sestavení pro auditory.
Průvodce řešením problémů
| Problém | Pravděpodobná příčina | Řešení |
|---|---|---|
| “Stream does not support reading” | Předán proud jen pro zápis (např. File.OpenWrite) | Použijte File.OpenRead nebo zajistěte, že CanRead je true. |
| “Object reference not set to an instance of an object” | Proud byl null nebo uvolněn před porovnáním | Ověřte inicializaci proudu a nechte using blok otevřený až po Compare(). |
| Špatný výkon u souborů >100 MB | Výchozí velikost bufferu je příliš malá, nebo příliš mnoho souběžných úloh | Zvyšte velikost bufferu, omezte souběžnost a profilujte pomocí dotMemory. |
| Chyby licence v produkci | Soubor licence chybí nebo je cesta nesprávná | Umístěte GroupDocs.Comparison.lic do kořenového adresáře aplikace a zavolejte SetLicense brzy při startu. |
| Poškozená data proudu | Přerušení sítě při stahování z cloudového úložiště | Ověřte délku proudu a kontrolní součet před porovnáním. |
Pokročilé konfigurační možnosti
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();
}
}
Definiční kotva: CompareOptions je konfigurační objekt, který vám umožňuje řídit vizuální stylování, ochranu heslem a typy změn, které jsou hlášeny.
Integrace s populárními .NET frameworky
Integrace s 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
};
}
}
Integrace s 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);
}
Závěr
Porovnání dokumentů založené na proudu v .NET vám poskytuje paměťově úsporný, cloud‑připravený a vysoce výkonný způsob, jak porovnávat Word soubory. Využitím třídy Comparer z GroupDocs.Comparison můžete pracovat přímo s objekty Stream, vyhnout se dočasným souborům a škálovat na tisíce souběžných porovnání. Dodržujte výše uvedené nejlepší postupy – správné uvolňování proudů, ladění bufferu a licencování – aby byla zajištěna robustní produkční implementace.
Zdroje
- Nákup GroupDocs
- Dokumentace GroupDocs.Comparison
- Reference API
- Stáhnout nejnovější verzi
- Zakoupit licenci
- Bezplatná zkušební verze
- Dočasná licence
- Komunitní podpora
Poslední aktualizace: 2026-05-31
Testováno s: GroupDocs.Comparison 25.4.0 for .NET
Autor: 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
}
}
}
}