Vergelijk Word-documenten C# met streamvergelijking in .NET
Inleiding
Als je compare word documents c# moet uitvoeren in een .NET‑applicatie terwijl je het geheugenverbruik laag houdt, ben je op de juiste plek. Traditionele bestandsgebaseerde vergelijking dwingt het volledige document in het RAM, wat snel een knelpunt wordt voor grote Word‑bestanden of cloud‑native scenario’s waarin je alleen een stream hebt. Deze tutorial laat je stap voor stap zien hoe je stream‑gebaseerde documentvergelijking uitvoert met GroupDocs.Comparison, compleet met praktijkvoorbeelden, prestatie‑tips en probleemoplossingsadvies.
Snelle antwoorden
- Welke bibliotheek behandelt stream‑vergelijking? GroupDocs.Comparison for .NET.
- Kan ik Word‑bestanden direct vergelijken vanuit een MemoryStream? Ja – geef gewoon de stream door aan de comparer.
- Heb ik een licentie nodig voor productie? Absoluut; een geldige GroupDocs.Comparison‑licentie verwijdert watermerken.
- Welke .NET‑versies worden ondersteund? .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5/6/7.
- Is async‑ondersteuning ingebouwd? Niet native, maar je kunt oproepen wikkelen in
Task.Runvoor basis‑async gedrag.
Wat is stream‑gebaseerde documentvergelijking?
De Comparer‑klasse in GroupDocs.Comparison leest documentgegevens van elke Stream‑implementatie, waardoor vergelijking mogelijk is zonder het bestand ooit naar schijf te schrijven. Dit maakt het ideaal voor cloudopslag, verwerking van grote bestanden en webservices met hoge gelijktijdigheid.
Waarom stream‑gebaseerde vergelijking gebruiken om Word‑documenten C# te vergelijken?
Stream‑gebaseerde vergelijking vermindert geheugenbelasting door gegevens in delen te verwerken in plaats van het volledige bestand te laden. GroupDocs.Comparison ondersteunt 50+ invoer‑ en uitvoerformaten—inclusief DOCX, PDF, PPTX en XLSX—en kan documenten met honderden pagina’s verwerken zonder de server‑RAM uit te putten. De aanpak sluit bovendien perfect aan bij Azure Blob, AWS S3 of elke HTTP‑gebaseerde opslag waar je een Stream ontvangt in plaats van een fysiek bestandspad.
Vereisten
- GroupDocs.Comparison for .NET (Versie 25.4.0 of later) – ondersteunt 50+ formaten.
- .NET Framework 4.6.1+ of .NET Core 2.0+ (inclusief .NET 5/6/7).
- Een IDE met C#‑ondersteuning (Visual Studio, VS Code of Rider).
- Basiskennis van C#‑streams (
FileStream,MemoryStream) enusing‑statements.
GroupDocs.Comparison voor .NET instellen
Installatiestappen
Installeren via NuGet Package Manager Console
Install-Package GroupDocs.Comparison -Version 25.4.0
Install-Package GroupDocs.Comparison -Version 25.4.0
Installeren via .NET CLI
dotnet add package GroupDocs.Comparison --version 25.4.0
dotnet add package GroupDocs.Comparison --version 25.4.0
Pro tip: Pin het versienummer om onverwachte breaking changes te voorkomen wanneer een nieuwe hoofdrelease verschijnt.
Licentie‑instelling (Belangrijk!)
GroupDocs.Comparison vereist een licentie voor productiegebruik. Je kunt beginnen met een gratis proefversie, een tijdelijke licentie verkrijgen voor proof‑of‑concept‑werk, of een volledige licentie aanschaffen voor onbeperkte implementaties. Bezoek GroupDocs Aankoop voor details.
Basislicentie‑initialisatie
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();
Nu ben je klaar om documenten van elke stream‑bron te vergelijken.
Hoe Word‑documenten C# vergelijken met streams?
Laad je bron‑ en doel‑Word‑bestanden als streams, geef ze door aan de Comparer en schrijf het resultaat naar een output‑stream. De volledige flow wordt hieronder geïllustreerd.
Stap 1: Bereid bron-, doel- en output‑streams voor
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));
}
Uitleg:
File.OpenReadmaakt alleen‑lees streams voor de twee Word‑bestanden.File.Createopent een alleen‑schrijf stream waarin het vergelijkingresultaat wordt opgeslagen.- De
using‑statements garanderen dat elke stream wordt vrijgegeven zodra het blok eindigt, waardoor bestandsvergrendelingen en geheugenlekken worden voorkomen.
Stap 2: Initialiseert de Comparer met de bron‑stream
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();
}
Definitie‑anker: De Comparer‑klasse is het kernonderdeel van GroupDocs.Comparison dat het laden, analyseren en genereren van verschillen tussen twee of meer document‑streams coördineert.
Stap 3: Voeg doel‑stream(s) toe
comparer.Add(targetStream);
// If you must reuse a stream, reset its position
stream.Position = 0;
Je kunt Add meerdere keren aanroepen om de bron te vergelijken met verschillende doelversies in één run.
Stap 4: Voer vergelijking uit en schrijf resultaat
ComparisonResult vertegenwoordigt de uitkomst van een vergelijking, met het diff‑document en gerelateerde 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();
}
Wat gebeurt hier?
Compare()verwerkt beide streams, detecteert inserties, deleties en opmaakwijzigingen, en retourneert eenComparisonResult‑object.Save()schrijft het gemarkeerde vergelijkingsdocument naar deresultStreamdie je eerder hebt aangemaakt.
Geavanceerde stream‑verwerking
Werken met MemoryStream (bijv. bestanden geüpload via HTTP)
Wanneer je applicatie een bestandsupload ontvangt, krijg je meestal een MemoryStream. Dezelfde API werkt zonder wijziging:
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
}
Waarom dit belangrijk is: Het gebruik van MemoryStream elimineert de noodzaak voor tijdelijke bestanden op schijf, wat de prestaties verbetert in stateless webservices en gecontaineriseerde omgevingen.
Veelvoorkomende valkuilen en oplossingen
Valkuil #1: Stream‑positie niet gereset
Probleem: Als een stream eerder is gelezen (bijv. voor validatie), kan de positie aan het einde staan, waardoor de comparer nul bytes leest.
Oplossing: Reset de positie voordat je de stream doorgeeft:
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
}
Valkuil #2: Vergeten streams te disposen
Probleem: Niet‑gedisposeerde streams houden bestands‑handles open, wat leidt tot “file in use”‑fouten.
Oplossing: Plaats streams altijd in using‑blokken of roep Dispose() expliciet aan, zoals getoond in de kernimplementatie.
Valkuil #3: Niet‑zoekbare streams gebruiken
Probleem: Sommige netwerk‑streams (bijv. NetworkStream) ondersteunen geen seeking, wat de comparer mogelijk nodig heeft.
Oplossing: Kopieer de niet‑zoekbare stream eerst naar een 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");
}
}
Prestatietips
Geheugengebruik optimaliseren
- Buffer‑grootte afstemmen: Voor documenten groter dan 50 MB, verhoog de interne buffer‑grootte naar 1 MB om lees‑schrijfcycli te verminderen.
- Async I/O: In ASP.NET Core, gebruik asynchrone bestands‑API’s (
FileStream.OpenReadAsync) om threads vrij te maken tijdens I/O.
Resource‑verbruik monitoren
- Performance‑counters: Houd
Process.PrivateMemorySize64bij vóór en na de vergelijking om het geheugenimpact te verifiëren. - Benchmarking: Voer
dotnet benchmark‑tests uit die bestandsgebaseerde versus stream‑gebaseerde benaderingen vergelijken; typische stream‑gebaseerde runs zijn 20‑30 % sneller op 200‑pagina DOCX‑bestanden.
Concurrency‑beheer
- Wachtrij‑systeem: Beperk gelijktijdige vergelijkingen tot het aantal CPU‑kernen om out‑of‑memory‑crashes te voorkomen.
- Vroeg disposen: Geef bron‑ en doel‑streams direct vrij nadat
Compare()terugkeert; de result‑stream kan open blijven tot je deze naar de client schrijft.
Praktijkvoorbeelden
Gebruikssituatie 1: Documentreview in webapplicatie
Een SaaS‑platform laat gebruikers twee versies van een contract uploaden voor naast‑elkaar review. De geüploade bestanden komen binnen als IFormFile‑objecten, die worden omgezet naar MemoryStream en direct vergeleken, waarbij een downloadbare DOCX met tracked changes wordt geretourneerd.
Gebruikssituatie 2: Batchverwerking vanuit cloudopslag
Een Azure Function wordt geactiveerd bij nieuwe blobs in een container, leest elke blob als een stream, vergelijkt deze met een baseline‑versie opgeslagen in een andere container, en schrijft het vergelijkingresultaat terug naar een “results”‑container.
Gebruikssituatie 3: Integratie met versiebeheer
Een DevOps‑pipeline haalt Word‑bestanden uit een Git‑repository, streamt ze naar GroupDocs.Comparison, en genereert een diff‑rapport dat wordt bijgevoegd bij het build‑artifact voor auditors.
Probleemoplossingsgids
| Issue | Likely Cause | Fix |
|---|---|---|
| “Stream ondersteunt geen lezen” | Een alleen‑schrijf stream doorgegeven (bijv. File.OpenWrite) | Gebruik File.OpenRead of zorg dat CanRead true is. |
| “Objectreferentie niet ingesteld op een instantie van een object” | Stream was null of werd disposed vóór vergelijking | Controleer stream‑initialisatie en houd het using‑blok open tot na Compare(). |
| Slechte prestaties op bestanden >100 MB | Standaard buffer‑grootte te klein, of te veel gelijktijdige taken | Verhoog de buffer‑grootte, beperk gelijktijdigheid, en profileer met dotMemory. |
| Licentiefouten in productie | Licentiebestand ontbreekt of pad onjuist | Plaats GroupDocs.Comparison.lic in de applicatieroot en roep SetLicense vroeg in de opstart aan. |
| Beschadigde stream‑gegevens | Netwerkonderbreking tijdens downloaden van cloudopslag | Valideer stream‑lengte en checksum vóór vergelijking. |
Geavanceerde configuratie‑opties
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();
}
}
Definitie‑anker: CompareOptions is een configuratie‑object waarmee je de visuele styling, wachtwoordbeveiliging en welke soorten wijzigingen worden gerapporteerd kunt regelen.
Integratie met populaire .NET‑frameworks
ASP.NET Core‑integratie
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‑integratie
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);
}
Conclusie
Stream‑gebaseerde documentvergelijking in .NET biedt je een geheugenefficiënte, cloud‑klare en hoog‑presterende manier om Word‑bestanden te vergelijken. Door gebruik te maken van GroupDocs.Comparison’s Comparer‑klasse kun je direct met Stream‑objecten werken, tijdelijke bestanden vermijden en opschalen naar duizenden gelijktijdige vergelijkingen. Volg de hierboven beschreven best practices—correcte stream‑dispositie, buffer‑afstemming en licentiëring—om een robuuste productie‑implementatie te waarborgen.
Bronnen
- GroupDocs Aankoop
- GroupDocs.Comparison Documentatie
- API‑referentie
- Laatste versie downloaden
- Licentie aanschaffen
- Gratis proefversie
- Tijdelijke licentie
- Community‑ondersteuning
Laatst bijgewerkt: 2026-05-31
Getest met: GroupDocs.Comparison 25.4.0 for .NET
Auteur: 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
}
}
}
}