Word-Dokumente in C# mit Stream-Vergleich in .NET vergleichen
Einführung
Wenn Sie compare word documents c# in einer .NET-Anwendung benötigen und dabei den Speicherverbrauch gering halten möchten, sind Sie hier richtig. Der herkömmliche dateibasierte Vergleich zwingt das gesamte Dokument in den RAM, was schnell zum Engpass bei großen Word‑Dateien oder cloud‑nativen Szenarien wird, in denen nur ein Stream verfügbar ist. Dieses Tutorial zeigt Ihnen Schritt für Schritt, wie Sie einen stream‑basierten Dokumentvergleich mit GroupDocs.Comparison durchführen, inklusive praxisnaher Beispiele, Performance‑Tipps und Fehlersuch‑Hinweisen.
Schnelle Antworten
- Welche Bibliothek unterstützt den Stream-Vergleich? GroupDocs.Comparison für .NET.
- Kann ich Word‑Dateien direkt aus einem MemoryStream vergleichen? Ja – übergeben Sie einfach den Stream an den Comparer.
- Benötige ich eine Lizenz für die Produktion? Absolut; eine gültige GroupDocs.Comparison‑Lizenz entfernt Wasserzeichen.
- Welche .NET‑Versionen werden unterstützt? .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5/6/7.
- Ist Async‑Unterstützung eingebaut? Nicht nativ, aber Sie können Aufrufe in
Task.Runeinbetten für einfaches Async‑Verhalten.
Was ist ein stream‑basierter Dokumentvergleich?
Die Comparer‑Klasse in GroupDocs.Comparison liest Dokumentdaten aus jeder Stream‑Implementierung und ermöglicht einen Vergleich, ohne die Datei jemals auf die Festplatte zu schreiben. Das macht sie ideal für Cloud‑Speicher, die Verarbeitung großer Dateien und hochgradig parallele Web‑Services.
Warum stream‑basierten Vergleich zum Vergleichen von Word‑Dokumenten in C# verwenden?
Stream‑basierter Vergleich reduziert den Speicherdruck, indem Daten in Chunks verarbeitet werden, anstatt die gesamte Datei zu laden. GroupDocs.Comparison unterstützt 50+ Eingabe‑ und Ausgabeformate — einschließlich DOCX, PDF, PPTX und XLSX — und kann mehrseitige Dokumente verarbeiten, ohne den Server‑RAM zu erschöpfen. Der Ansatz passt zudem perfekt zu Azure Blob, AWS S3 oder jedem HTTP‑basierten Speicher, bei dem Sie einen Stream anstelle eines physischen Dateipfads erhalten.
Voraussetzungen
- GroupDocs.Comparison für .NET (Version 25.4.0 oder neuer) – unterstützt 50+ Formate.
- .NET Framework 4.6.1+ oder .NET Core 2.0+ (inklusive .NET 5/6/7).
- Eine IDE mit C#‑Unterstützung (Visual Studio, VS Code oder Rider).
- Grundkenntnisse von C#‑Streams (
FileStream,MemoryStream) undusing‑Anweisungen.
Einrichtung von GroupDocs.Comparison für .NET
Installationsschritte
Verwendung der NuGet Package Manager Console
Install-Package GroupDocs.Comparison -Version 25.4.0
Install-Package GroupDocs.Comparison -Version 25.4.0
Verwendung der .NET CLI
dotnet add package GroupDocs.Comparison --version 25.4.0
dotnet add package GroupDocs.Comparison --version 25.4.0
Pro Tipp: Fixieren Sie die Versionsnummer, um unerwartete Breaking Changes bei einer neuen Hauptversion zu vermeiden.
Lizenzsetup (Wichtig!)
GroupDocs.Comparison erfordert eine Lizenz für den Produktionseinsatz. Sie können mit einer kostenlosen Testversion beginnen, eine temporäre Lizenz für Proof‑of‑Concept‑Arbeiten erhalten oder eine Voll‑Lizenz für unbegrenzte Deployments erwerben. Besuchen Sie GroupDocs Kauf für Details.
Grundlegende Lizenzinitialisierung
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();
Jetzt sind Sie bereit, Dokumente aus jeder Stream‑Quelle zu vergleichen.
Wie vergleicht man Word‑Dokumente in C# mithilfe von Streams?
Laden Sie Ihre Quell‑ und Zieldateien als Streams, übergeben Sie sie dem Comparer und schreiben Sie das Ergebnis in einen Ausgabestream. Der komplette Ablauf ist unten dargestellt.
Schritt 1: Quell‑, Ziel‑ und Ausgabestreams vorbereiten
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));
}
Erklärung:
File.OpenReaderstellt nur‑Lese‑Streams für die beiden Word‑Dateien.File.Createöffnet einen Schreib‑Stream, in dem das Vergleichsergebnis gespeichert wird.- Die
using‑Anweisungen stellen sicher, dass jeder Stream sofort nach Verlassen des Blocks freigegeben wird, wodurch Dateisperren und Speicherlecks vermieden werden.
Schritt 2: Initialisieren des Comparers mit dem Quell‑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();
}
Definition anchor: Die Comparer‑Klasse ist die Kernkomponente von GroupDocs.Comparison, die das Laden, Analysieren und Erzeugen von Unterschieden zwischen zwei oder mehr Dokument‑Streams orchestriert.
Schritt 3: Ziel‑Stream(s) hinzufügen
comparer.Add(targetStream);
// If you must reuse a stream, reset its position
stream.Position = 0;
Sie können Add mehrfach aufrufen, um die Quelle gegen mehrere Zielversionen in einem Durchlauf zu vergleichen.
Schritt 4: Vergleich ausführen und Ergebnis schreiben
ComparisonResult stellt das Ergebnis eines Vergleichs dar und enthält das Diff‑Dokument sowie zugehörige Metadaten.
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();
}
Was passiert hier?
Compare()verarbeitet beide Streams, erkennt Einfügungen, Löschungen und Formatierungsänderungen und gibt einComparisonResult‑Objekt zurück.Save()schreibt das hervorgehobene Vergleichsdokument in den zuvor erstelltenresultStream.
Erweiterte Stream‑Verarbeitung
Arbeiten mit MemoryStream (z. B. Dateien, die über HTTP hochgeladen werden)
Wenn Ihre Anwendung einen Datei‑Upload erhält, bekommen Sie typischerweise einen MemoryStream. Die gleiche API funktioniert ohne Änderungen:
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
}
Warum das wichtig ist: Die Verwendung von MemoryStream eliminiert die Notwendigkeit temporärer Dateien auf der Festplatte, was die Leistung in zustandslosen Web‑Services und containerisierten Umgebungen verbessert.
Häufige Fallstricke und Lösungen
Fallstrick #1: Stream‑Position nicht zurückgesetzt
Problem: Wenn ein Stream zuvor gelesen wurde (z. B. zur Validierung), befindet sich die Position am Ende, sodass der Comparer keine Bytes liest.
Lösung: Setzen Sie die Position zurück, bevor Sie den Stream übergeben:
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
}
Fallstrick #2: Vergessen, Streams zu entsorgen
Problem: Nicht freigegebene Streams halten Dateihandles offen, was zu „Datei wird verwendet“-Fehlern führt.
Lösung: Immer Streams in using‑Blöcken einbetten oder Dispose() explizit aufrufen, wie in der Kernimplementierung gezeigt.
Fallstrick #3: Verwendung nicht‑suchbarer Streams
Problem: Einige Netzwerk‑Streams (z. B. NetworkStream) unterstützen kein Suchen, was der Comparer benötigen könnte.
Lösung: Kopieren Sie den nicht‑suchbaren Stream zuerst in einen 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");
}
}
Performance‑Best Practices
Speicherverbrauch optimieren
- Puffergrößen‑Optimierung: Für Dokumente größer als 50 MB die interne Puffergröße auf 1 MB erhöhen, um Lese‑/Schreibzyklen zu reduzieren.
- Async‑I/O: In ASP.NET Core asynchrone Datei‑APIs (
FileStream.OpenReadAsync) nutzen, um Threads während I/O freizugeben.
Ressourcenverbrauch überwachen
- Performance‑Counter:
Process.PrivateMemorySize64vor und nach dem Vergleich messen, um den Speicherimpact zu prüfen. - Benchmarking:
dotnet benchmark‑Tests ausführen, die dateibasierte gegen stream‑basierte Ansätze vergleichen; typische stream‑basierte Durchläufe sind 20‑30 % schneller bei 200‑Seiten‑DOCX‑Dateien.
Nebenläufigkeits‑Steuerung
- Queue‑System: Gleichzeitige Vergleiche auf die Anzahl der CPU‑Kerne begrenzen, um Out‑of‑Memory‑Abstürze zu vermeiden.
- Frühzeitiges Freigeben: Quell‑ und Ziel‑Streams sofort nach Rückkehr von
Compare()freigeben; der Ergebnis‑Stream kann bis zum Schreiben an den Client offen bleiben.
Praxisbeispiele
Anwendungsfall 1: Dokumenten‑Review in Web‑Anwendung
Eine SaaS‑Plattform lässt Nutzer zwei Versionen eines Vertrags hochladen, um sie nebeneinander zu prüfen. Die hochgeladenen Dateien kommen als IFormFile‑Objekte, werden in MemoryStream konvertiert und sofort verglichen, wobei ein herunterladbares DOCX mit nachverfolgten Änderungen zurückgegeben wird.
Anwendungsfall 2: Batch‑Verarbeitung aus Cloud‑Speicher
Eine Azure‑Function wird bei neuen Blobs in einem Container ausgelöst, liest jedes Blob als Stream, vergleicht es mit einer Basisversion aus einem anderen Container und schreibt das Vergleichsergebnis zurück in einen „results“-Container.
Anwendungsfall 3: Integration in Versionskontrolle
Eine DevOps‑Pipeline extrahiert Word‑Dateien aus einem Git‑Repository, streamt sie in GroupDocs.Comparison und erzeugt einen Diff‑Report, der dem Build‑Artefakt für Auditoren beigefügt wird.
Fehlersuch‑Leitfaden
| Problem | Wahrscheinliche Ursache | Lösung |
|---|---|---|
| „Stream unterstützt kein Lesen“ | Ein Schreib‑Only‑Stream wurde übergeben (z. B. File.OpenWrite) | Verwenden Sie File.OpenRead oder stellen Sie sicher, dass CanRead true ist. |
| „Objektreferenz nicht auf eine Instanz eines Objekts gesetzt“ | Stream war null oder vor dem Vergleich entsorgt | Stream‑Initialisierung prüfen und den using‑Block bis nach Compare() offen halten. |
| Schlechte Leistung bei Dateien > 100 MB | Standard‑Puffergröße zu klein oder zu viele gleichzeitige Tasks | Puffergröße erhöhen, Parallelität begrenzen und mit dotMemory profilieren. |
| Lizenzierungsfehler in der Produktion | Lizenzdatei fehlt oder Pfad ist falsch | GroupDocs.Comparison.lic im Anwendungsverzeichnis ablegen und SetLicense früh im Startup aufrufen. |
| Beschädigte Stream‑Daten | Netzwerkunterbrechung beim Herunterladen aus Cloud‑Speicher | Stream‑Länge und Prüfsumme vor dem Vergleich validieren. |
Erweiterte Konfigurationsoptionen
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();
}
}
Definition anchor: CompareOptions ist ein Konfigurationsobjekt, mit dem Sie das visuelle Styling, den Passwortschutz und die zu meldenden Änderungsarten steuern können.
Integration mit gängigen .NET‑Frameworks
ASP.NET Core Integration
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 Integration
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);
}
Fazit
Stream‑basierter Dokumentvergleich in .NET bietet eine speichereffiziente, cloud‑bereite und hoch‑performante Methode zum Vergleich von Word‑Dateien. Durch die Nutzung der Comparer‑Klasse von GroupDocs.Comparison können Sie direkt mit Stream‑Objekten arbeiten, temporäre Dateien vermeiden und tausende gleichzeitige Vergleiche skalieren. Befolgen Sie die oben beschriebenen Best Practices — richtige Stream‑Entsorgung, Puffer‑Tuning und Lizenzierung — um eine robuste Produktionsimplementierung sicherzustellen.
Ressourcen
- GroupDocs Kauf
- GroupDocs.Comparison Dokumentation
- API‑Referenz
- Neueste Version herunterladen
- Lizenz kaufen
- Kostenlose Testversion
- Temporäre Lizenz
- Community‑Support
Zuletzt aktualisiert: 2026-05-31
Getestet mit: GroupDocs.Comparison 25.4.0 für .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
}
}
}
}