Σύγκριση εγγράφων Word C# με σύγκριση ροής σε .NET

Εισαγωγή

Αν χρειάζεστε συγκρίση εγγράφων Word c# σε μια εφαρμογή .NET ενώ διατηρείτε τη χρήση μνήμης χαμηλή, βρίσκεστε στο σωστό μέρος. Η παραδοσιακή σύγκριση βάσει αρχείου αναγκάζει ολόκληρο το έγγραφο να φορτωθεί στη RAM, κάτι που γρήγορα γίνεται εμπόδιο για μεγάλα αρχεία Word ή σενάρια cloud‑native όπου έχετε μόνο μια ροή. Αυτό το tutorial σας δείχνει, βήμα προς βήμα, πώς να εκτελέσετε σύγκριση εγγράφων με βάση τη ροή χρησιμοποιώντας το GroupDocs.Comparison, με πραγματικά παραδείγματα, συμβουλές απόδοσης και οδηγίες αντιμετώπισης προβλημάτων.

Γρήγορες Απαντήσεις

  • Ποια βιβλιοθήκη διαχειρίζεται τη σύγκριση ροής; GroupDocs.Comparison for .NET.
  • Μπορώ να συγκρίνω αρχεία Word απευθείας από MemoryStream; Ναι – απλώς περάστε τη ροή στον συγκριτή.
  • Χρειάζομαι άδεια για παραγωγή; Απόλυτα· μια έγκυρη άδεια GroupDocs.Comparison αφαιρεί τα υδατογραφήματα.
  • Ποιες εκδόσεις .NET υποστηρίζονται; .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5/6/7.
  • Υπάρχει ενσωματωμένη υποστήριξη async; Δεν υπάρχει εγγενώς, αλλά μπορείτε να τυλίξετε τις κλήσεις σε Task.Run για βασική ασύγχρονη συμπεριφορά.

Τι είναι η σύγκριση εγγράφων με βάση τη ροή;

Η κλάση Comparer στο GroupDocs.Comparison διαβάζει τα δεδομένα του εγγράφου από οποιαδήποτε υλοποίηση Stream, επιτρέποντας τη σύγκριση χωρίς ποτέ να γράφεται το αρχείο στο δίσκο. Αυτό την καθιστά ιδανική για αποθήκευση στο cloud, επεξεργασία μεγάλων αρχείων και υπηρεσίες web υψηλής ταυτόχρονης χρήσης.

Γιατί να χρησιμοποιήσετε σύγκριση με βάση τη ροή για τη σύγκριση εγγράφων Word C#;

Η σύγκριση με βάση τη ροή μειώνει την πίεση στη μνήμη επεξεργαζόμενη δεδομένα σε τμήματα αντί να φορτώνεται ολόκληρο το αρχείο. Το GroupDocs.Comparison υποστηρίζει 50+ μορφές εισόδου και εξόδου—συμπεριλαμβανομένων DOCX, PDF, PPTX και XLSX—και μπορεί να διαχειριστεί έγγραφα εκατοντάδων σελίδων χωρίς να εξαντλεί τη μνήμη του διακομιστή. Η προσέγγιση ευθυγραμμίζεται τέλεια με Azure Blob, AWS S3 ή οποιαδήποτε αποθήκευση βασισμένη σε HTTP όπου λαμβάνετε μια Stream αντί για φυσική διαδρομή αρχείου.

Προαπαιτούμενα

  • GroupDocs.Comparison for .NET (Version 25.4.0 or later) – υποστηρίζει 50+ μορφές.
  • .NET Framework 4.6.1+ ή .NET Core 2.0+ (συμπεριλαμβανομένων .NET 5/6/7).
  • Ένα IDE με υποστήριξη C# (Visual Studio, VS Code ή Rider).
  • Βασικές γνώσεις για ροές C# (FileStream, MemoryStream) και δηλώσεις using.

Ρύθμιση GroupDocs.Comparison για .NET

Βήματα Εγκατάστασης

Χρήση του NuGet Package Manager Console

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 Purchase για λεπτομέρειες.

Βασική Αρχικοποίηση Άδειας

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 ως ροές, δώστε τα στο Comparer και γράψτε το αποτέλεσμα σε μια ροή εξόδου. Η πλήρης ροή απεικονίζεται παρακάτω.

Βήμα 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 εξαλείφει την ανάγκη για προσωρινά αρχεία στο δίσκο, βελτιώνοντας την απόδοση σε αδιάσπαστες web υπηρεσίες και περιβάλλοντα με κοντέινερ.

Συνηθισμένα Πιθανά Προβλήματα και Λύσεις

Παγίδα #1: Η θέση της ροής δεν επαναφέρθηκε

Πρόβλημα: Εάν μια ροή έχει διαβαστεί νωρίτερα (π.χ., για επικύρωση), η θέση της μπορεί να βρίσκεται στο τέλος, προκαλώντας στον συγκριτή ανάγνωση μηδενικών bytes.
Λύση: Επαναφέρετε τη θέση πριν περάσετε τη ροή:

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: Ξεχάσιμο της απελευθέρωσης των ροών

Πρόβλημα: Οι μη απελευθερωμένες ροές κρατούν ανοιχτά handles αρχείων, οδηγώντας σε σφάλματα “αρχείο σε χρήση”.
Λύση: Πάντα τυλίξτε τις ροές σε μπλοκ 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");
    }
}

Βέλτιστες Πρακτικές Απόδοσης

Βελτιστοποίηση Χρήσης Μνήμης

  • Ρύθμιση Μεγέθους Buffer: Για έγγραφα μεγαλύτερα από 50 MB, αυξήστε το εσωτερικό μέγεθος buffer στα 1 MB για μείωση των κύκλων ανάγνωσης‑εγγραφής.
  • Async I/O: Στο ASP.NET Core, χρησιμοποιήστε ασύγχρονες API αρχείων (FileStream.OpenReadAsync) για ελευθέρωση threads κατά τη διάρκεια I/O.

Παρακολούθηση Κατανάλωσης Πόρων

  • Performance Counters: Παρακολουθήστε το Process.PrivateMemorySize64 πριν και μετά τη σύγκριση για επαλήθευση του αντίκτυπου στη μνήμη.
  • Benchmarking: Εκτελέστε δοκιμές dotnet benchmark συγκρίνοντας προσεγγίσεις βάσει αρχείου vs. βάσει ροής· οι τυπικές εκτελέσεις με ροή είναι 20‑30 % γρηγορότερες σε αρχεία DOCX 200 σελίδων.

Έλεγχος Συγχρονικότητας

  • Queue System: Περιορίστε τις ταυτόχρονες συγκρίσεις στον αριθμό των πυρήνων CPU για αποφυγή καταρρεύσεων λόγω έλλειψης μνήμης.
  • Dispose Early: Απελευθερώστε τις ροές πηγής και στόχου αμέσως μετά την επιστροφή του Compare()· η ροή αποτελέσματος μπορεί να παραμείνει ανοιχτή μέχρι να την γράψετε στον πελάτη.

Πραγματικές Περιπτώσεις Χρήσης

Περίπτωση Χρήσης 1: Ανασκόπηση Εγγράφων σε Εφαρμογή Web

Μια πλατφόρμα SaaS επιτρέπει στους χρήστες να ανεβάσουν δύο εκδόσεις ενός συμβολαίου για παράλληλη ανασκόπηση. Τα ανεβασμένα αρχεία φθάνουν ως αντικείμενα IFormFile, μετατρέπονται σε MemoryStream και συγκρίνονται άμεσα, επιστρέφοντας ένα λήψιμο DOCX με παρακολουθούμενες αλλαγές.

Περίπτωση Χρήσης 2: Μαζική Επεξεργασία από Αποθήκευση Cloud

Μια Azure Function ενεργοποιείται όταν δημιουργούνται νέα blobs σε ένα container, διαβάζει κάθε blob ως ροή, το συγκρίνει με μια βασική έκδοση αποθηκευμένη σε άλλο container, και γράφει το αποτέλεσμα σε ένα “results” container.

Περίπτωση Χρήσης 3: Ενσωμάτωση Ελέγχου Εκδόσεων

Μια pipeline DevOps εξάγει αρχεία Word από αποθετήριο Git, τα στέλνει ως ροές στο GroupDocs.Comparison και δημιουργεί μια αναφορά diff που επισυνάπτεται στο artifact του build για τους ελεγκτές.

Οδηγός Επίλυσης Προβλημάτων

ΠρόβλημαΠιθανή ΑιτίαΔιόρθωση
“Stream does not support reading”Παράδοση ροής μόνο για εγγραφή (π.χ., File.OpenWrite)Χρησιμοποιήστε File.OpenRead ή βεβαιωθείτε ότι CanRead είναι true.
“Object reference not set to an instance of an object”Η ροή ήταν null ή απελευθερώθηκε πριν τη σύγκρισηΕπαληθεύστε την αρχικοποίηση της ροής και διατηρήστε το μπλοκ using ανοιχτό μέχρι το Compare().
Κακή απόδοση σε αρχεία 100 MB+Το προεπιλεγμένο μέγεθος buffer είναι πολύ μικρό ή υπάρχουν πολλές ταυτόχρονες εργασίεςΑυξήστε το μέγεθος buffer, περιορίστε τη συγχρονικότητα και κάντε profiling με dotMemory.
Σφάλματα αδειοδότησης σε παραγωγήΤο αρχείο άδειας λείπει ή η διαδρομή είναι λανθασμένηΤοποθετήστε το GroupDocs.Comparison.lic στη ρίζα της εφαρμογής και καλέστε SetLicense νωρίς στην εκκίνηση.
Κατεστραμμένα δεδομένα ροήςΔιακοπή δικτύου κατά τη λήψη από cloud storageΕπικυρώστε το μήκος της ροής και το 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 Frameworks

Ενσωμάτωση 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 προσφέρει έναν αποδοτικό σε μνήμη, έτοιμο για cloud, και υψηλής απόδοσης τρόπο σύγκρισης αρχείων Word. Εκμεταλλευόμενοι την κλάση Comparer του GroupDocs.Comparison, μπορείτε να εργάζεστε απευθείας με αντικείμενα Stream, να αποφεύγετε προσωρινά αρχεία και να κλιμακώσετε σε χιλιάδες ταυτόχρονες συγκρίσεις. Ακολουθήστε τις βέλτιστες πρακτικές που περιγράφηκαν παραπάνω—σωστή απελευθέρωση ροών, ρύθμιση buffer και αδειοδότηση—για να εξασφαλίσετε μια αξιόπιστη υλοποίηση παραγωγής.

Πόροι

Τελευταία ενημέρωση: 2026-05-31
Δοκιμάστηκε με: GroupDocs.Comparison 25.4.0 for .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
            }
        }
    }
}

Σχετικά Μαθήματα