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.Run for 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) a using bloků.

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.OpenRead vytváří jen pro čtení proudy pro oba Word soubory.
  • File.Create otevírá jen pro zápis proud, kam bude uložen výsledek porovnání.
  • using bloky 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í objekt ComparisonResult.
  • Save() zapíše zvýrazněný dokument porovnání do resultStream, 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.PrivateMemorySize64 před a po porovnání pro ověření dopadu na paměť.
  • Benchmarking: Spusťte testy dotnet benchmark porovná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émPravdě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ímOvěřte inicializaci proudu a nechte using blok otevřený až po Compare().
Špatný výkon u souborů >100 MBVýchozí velikost bufferu je příliš malá, nebo příliš mnoho souběžných úlohZvyšte velikost bufferu, omezte souběžnost a profilujte pomocí dotMemory.
Chyby licence v produkciSoubor 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 prouduPř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


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
            }
        }
    }
}

Související tutoriály