Σύγκριση φακέλων java – οδηγός χρήσης του GroupDocs.Comparison
Έχετε ξοδέψει ώρες ελέγχοντας χειροκίνητα ποια αρχεία έχουν αλλάξει μεταξύ δύο εκδόσεων ενός έργου; Δεν είστε μόνοι. GroupDocs.Comparison for Java κάνει αυτή τη βαρετή εργασία εύκολη, επιτρέποντάς σας να συγκρίνετε δύο φακέλους με μία μόνο κλήση API. Σε αυτό το tutorial θα μάθετε πώς να compare folders java αποτελεσματικά, από την αρχική ρύθμιση μέχρι την προχωρημένη βελτιστοποίηση απόδοσης για τεράστιες βάσεις κώδικα.
GroupDocs.Comparison for Java είναι μια βιβλιοθήκη που επιτρέπει προγραμματιστική σύγκριση εγγράφων και καταλόγων. Υποστηρίζει πάνω από 70 μορφές εισόδου και εξόδου και μπορεί να επεξεργαστεί καταλόγους με έως και 10 000 αρχεία χωρίς να φορτώνει ολόκληρο το σύνολο αρχείων στη μνήμη, καθιστώντας την μια αξιόπιστη επιλογή για ελέγχους σε επίπεδο επιχείρησης.
Γρήγορες απαντήσεις
- Ποια είναι η κύρια βιβλιοθήκη;
groupdocs comparison java - Υποστηριζόμενη έκδοση Java; Java 8 ή νεότερη
- Τυπικός χρόνος εγκατάστασης; 10–15 λεπτά για μια βασική σύγκριση
- Απαίτηση άδειας; Ναι – απαιτείται δοκιμαστική ή εμπορική άδεια
- Μορφές εξόδου; HTML (προεπιλογή) ή PDF
Τι είναι το compare folders java;
Η φράση “compare folders java” αναφέρεται στη χρήση ενός API βασισμένου σε Java για τον εντοπισμό διαφορών — προστιθέμενων, αφαιρεθέντων ή τροποποιημένων αρχείων — μεταξύ δύο δέντρων καταλόγων. Το GroupDocs.Comparison παρέχει έναν υψηλού επιπέδου, ανεξάρτητο από το σύστημα αρχείων τρόπο εκτέλεσης αυτής της λειτουργίας, επιστρέφοντας μια λεπτομερή αναφορά σε HTML ή PDF που επισημαίνει κάθε αλλαγή.
Γιατί η σύγκριση φακέλων java είναι σημαντική (πιο πολύ από ό,τι νομίζετε)
Η σύγκριση καταλόγων δεν αφορά μόνο τον εντοπισμό ελλιπών αρχείων· αποτελεί κρίσιμο σημείο ελέγχου για την ακεραιότητα των δεδομένων, τη συμμόρφωση με κανονισμούς και τη σταθερότητα των εκδόσεων. Αυτοματοποιώντας τη διαδικασία εξαλείφετε τα ανθρώπινα λάθη, επιταχύνετε τους ελέγχους και αποκτάτε μια μοναδική πηγή αλήθειας που μπορεί να αρχειοθετηθεί για μελλοντική αναφορά.
Ποσοτικοποιημένα οφέλη
- Ταχύτητα: Επεξεργάζεται καταλόγους 5 000 αρχείων σε λιγότερο από 30 δευτερόλεπτα σε τυπικό διακομιστή 8‑πυρήνων.
- Κάλυψη: Ανιχνεύει αλλαγές σε πάνω από 70 τύπους εγγράφων, από DOCX έως PNG.
- Κλιμακωσιμότητα: Διαχειρίζεται αρχεία έως 2 GB το καθένα χωρίς να εξαντλεί τη μνήμη heap της JVM όταν είναι ενεργοποιημένη η λειτουργία streaming.
- Ακρίβεια: Αναφέρει διαφορές με 99,9 % πιστότητα, διατηρώντας τη διάταξη, τους πίνακες και τις εικόνες.
Προαπαιτούμενα και απαιτήσεις εγκατάστασης
Πριν αρχίσουμε τον κώδικα, βεβαιωθείτε ότι το περιβάλλον σας είναι έτοιμο. Ακολουθεί τι θα χρειαστείτε (και γιατί):
Απαραίτητα απαιτούμενα
- Java 8 ή νεότερη – Το GroupDocs.Comparison χρησιμοποιεί σύγχρονες δυνατότητες γλώσσας και API.
- Maven 3.6+ – Για αξιόπιστη διαχείριση εξαρτήσεων· η χειροκίνητη διαχείριση JAR είναι επιρρεπής σε σφάλματα.
- IDE με καλή υποστήριξη Java – Συνιστώνται IntelliJ IDEA ή Eclipse για αποσφαλμάτωση και refactoring.
- Τουλάχιστον 2 GB RAM – Οι συγκρίσεις μεγάλων καταλόγων μπορούν να καταναλώσουν σημαντική μνήμη, ειδικά κατά τη δημιουργία αναφορών HTML.
Γνώσεις προαπαιτούμενα
- Βασική σύνταξη Java (βρόχοι, διαχείριση εξαιρέσεων, try‑with‑resources).
- Εξοικείωση με file I/O (
java.nio.file.Path,FilesAPI). - Κατανόηση των ενοτήτων
<dependency>και<repository>του Maven.
Προαιρετικά αλλά χρήσιμα
- Εμπειρία με SLF4J/Logback για logging.
- Γνώσεις πολυνηματισμού αν σκοπεύετε να παραλληλοποιήσετε τις συγκρίσεις.
- Βασικές γνώσεις HTML για προσαρμογή της παραγόμενης αναφοράς.
Ρύθμιση GroupDocs.Comparison για Java
Ας ενσωματώσουμε σωστά αυτή τη βιβλιοθήκη στο έργο σας. Η εγκατάσταση είναι απλή, αλλά υπάρχουν μερικές παγίδες που πρέπει να προσέξετε.
Διαμόρφωση Maven
Προσθέστε την παρακάτω εξάρτηση και αποθετήριο στο pom.xml. Φροντίστε να αντικαταστήσετε το placeholder έκδοσης με τον τελευταίο αριθμό έκδοσης από την επίσημη σελίδα του GroupDocs.
<dependency>
<groupId>com.groupdocs</groupId>
<artifactId>groupdocs-comparison</artifactId>
<version>25.2</version>
</dependency>
<repository>
<id>groupdocs-repo</id>
<url>https://repo.groupdocs.com/maven2</url>
</repository>
Συμβουλή: Πάντα ελέγχετε τον αριθμό έκδοσης στη σελίδα λήψης του προϊόντος· οι νεότερες εκδόσεις περιλαμβάνουν διορθώσεις απόδοσης και πρόσθετη υποστήριξη μορφών.
Ρύθμιση άδειας (μη παραλείψετε αυτό)
Το GroupDocs δεν είναι δωρεάν, αλλά προσφέρει διάφορες επιλογές αδειοδότησης:
- Δωρεάν δοκιμή: Δοκιμή 30 ημερών με πλήρες σύνολο λειτουργιών—ιδανική για αξιολόγηση.
- Προσωρινή άδεια: Εκτεταμένη δοκιμή για περιβάλλοντα ανάπτυξης και δοκιμών.
- Εμπορική άδεια: Απαιτείται για παραγωγικές εγκαταστάσεις.
Αποκτήστε την άδειά σας από:
- Purchase a license για παραγωγή
- Get a temporary license για εκτεταμένες δοκιμές
Βασική αρχικοποίηση και δοκιμή
Μόλις η κατασκευή Maven ολοκληρωθεί επιτυχώς, δημιουργήστε μια απλή κλάση δοκιμής που φορτώνει την άδεια και εκτελεί μια ελάχιστη σύγκριση. Αν το πρόγραμμα ξεκινήσει χωρίς εξαίρεση, το περιβάλλον σας είναι σωστά διαμορφωμένο.
import com.groupdocs.comparison.Comparison;
import com.groupdocs.comparison.License;
public class InitTest {
public static void main(String[] args) throws Exception {
License license = new License();
license.setLicense("GroupDocs.Comparison.lic");
// Simple sanity check
Comparison comparison = new Comparison();
System.out.println("GroupDocs.Comparison initialized successfully.");
}
}
Αν αυτό εκτελεστεί χωρίς σφάλματα, είστε έτοιμοι να προχωρήσετε. Αν όχι, ελέγξτε ξανά τις ρυθμίσεις Maven και βεβαιωθείτε ότι η μηχανή σας μπορεί να προσεγγίσει τον διακομιστή αδειοδότησης του GroupDocs.
Κύρια υλοποίηση: σύγκριση καταλόγων
Τώρα έρχεται το κύριο μέρος — η πραγματική σύγκριση καταλόγων. Θα ξεκινήσουμε με μια βασική υλοποίηση και στη συνέχεια θα προσθέσουμε προχωρημένα χαρακτηριστικά.
Πώς να συγκρίνετε φακέλους java;
Φορτώστε δύο διαδρομές καταλόγου, διαμορφώστε τις επιλογές σύγκρισης και καλέστε το API. Σε μόλις τρεις γραμμές κώδικα μπορείτε να δημιουργήσετε μια πλήρη αναφορά diff σε HTML που καταγράφει κάθε προστιθέμενο, διαγραμμένο ή τροποποιημένο αρχείο.
Comparison comparison = new Comparison();
comparison.compare("C:/Project/v1", "C:/Project/v2", "C:/Reports/diff.html");
Η μέθοδος compare σαρώει και τους δύο φακέλους αναδρομικά, ταιριάζει αρχεία με βάση το όνομα και γράφει μια οπτική αναφορά HTML στην καθορισμένη τοποθεσία. Η αναφορά επισημαίνει αλλαγές γραμμή‑προς‑γραμμή για αρχεία κειμένου και εμφανίζει προεπισκοπήσεις πλάι‑πλάι για εικόνες και PDF.
Η κλάση Comparison είναι το κύριο σημείο εισόδου του API που εκτελεί τη σύγκριση καταλόγων και παράγει την αναφορά.
Τυλίξτε την κλήση σε ένα μπλοκ try‑with‑resources (ή χρησιμοποιήστε τη μέθοδο close του αντικειμένου Comparison) ώστε να εξασφαλίσετε ότι όλοι οι χειριστές αρχείων απελευθερώνονται άμεσα, ειδικά όταν επεξεργάζεστε χιλιάδες αρχεία.
Προχωρημένες επιλογές διαμόρφωσης
Η βασική ρύθμιση καλύπτει τις περισσότερες περιπτώσεις, αλλά σε πραγματικά έργα συχνά απαιτείται πιο λεπτομερής έλεγχος.
Προσαρμογή μορφών εξόδου
Το GroupDocs.Comparison μπορεί να εξάγει αναφορές ως PDF, DOCX ή απλό HTML. Η αλλαγή μορφής γίνεται απλώς αλλάζοντας την επέκταση αρχείου στην κλήση compare.
Φιλτράρισμα αρχείων και καταλόγων
Αν σας ενδιαφέρουν μόνο συγκεκριμένοι τύποι αρχείων (π.χ. .java και .xml), παρέχετε ένα predicate φίλτρου για να παραλείψετε τα άσχετα αρχεία και να βελτιώσετε δραστικά την απόδοση.
comparison.setFileFilter(path -> path.toString().endsWith(".java") || path.toString().endsWith(".xml"));
Συνηθισμένα προβλήματα και λύσεις
Ας αντιμετωπίσουμε τα ζητήματα που πιθανότατα θα συναντήσετε (επειδή ο νόμος του Murphy ισχύει και στον κώδικα).
Πρόβλημα 1: OutOfMemoryError με μεγάλους καταλόγους
Άμεση απάντηση: Αυξήστε το μέγεθος heap της JVM (-Xmx4g ή μεγαλύτερο) και ενεργοποιήστε τη λειτουργία streaming στις επιλογές Comparison ώστε να επεξεργάζεται αρχεία διαδοχικά αντί να τα φορτώνει όλα στη μνήμη.
Σε καταλόγους με δεκάδες χιλιάδες αρχεία, η προεπιλεγμένη προσέγγιση in‑memory μπορεί να ξεπεράσει το heap. Η λειτουργία streaming διαβάζει κάθε αρχείο κατ’ ανάγκη, διατηρώντας το αποτύπωμα μνήμης κάτω από 200 MB ακόμη και για εκτελέσεις 10 000 αρχείων.
Πρόβλημα 2: FileNotFoundException παρά τις σωστές διαδρομές
Άμεση απάντηση: Βεβαιωθείτε ότι η διαδικασία Java έχει δικαιώματα ανάγνωσης για τους πηγαίους καταλόγους και δικαιώματα εγγραφής για το φάκελο εξόδου· επίσης ελέγξτε ότι τυχόν κενά ή ειδικοί χαρακτήρες στη διαδρομή έχουν σωστά escaped.
Συνηθισμένοι λόγοι είναι περιορισμοί ACL του λειτουργικού συστήματος, δικτυακές κοινόχρηστες που απαιτούν πιστοποίηση και χαρακτήρες Unicode που χρειάζονται ρητή διαχείριση μέσω java.nio.file.Paths.
Πρόβλημα 3: Η σύγκριση διαρκεί ατέρμονα
Άμεση απάντηση: Εφαρμόστε φίλτρα αρχείων για να εξαιρέσετε μεγάλα δυαδικά περιουσιακά στοιχεία, ενεργοποιήστε την πολυνηματική επεξεργασία για ανεξάρτητα υπο‑φακέλους και παρακολουθήστε την πρόοδο με έναν listener callback για να εντοπίσετε τα bottlenecks νωρίς.
Η παραλληλοποίηση συγκρίσεων υπο‑καταλόγων μπορεί να μειώσει το χρόνο εκτέλεσης έως και 70 % σε διακομιστή 8‑πυρήνων, ενώ τα callbacks προόδου σας επιτρέπουν να εμφανίσετε μια απλή γραμμή προόδου στην κονσόλα για μακροχρόνιες εργασίες.
Βελτιστοποίηση απόδοσης για συγκρίσεις μεγάλης κλίμακας
Όταν εργάζεστε με καταλόγους χιλιάδων αρχείων, η απόδοση γίνεται κρίσιμη. Ακολουθούν πρακτικές βελτιστοποίησης:
Καλές πρακτικές διαχείρισης μνήμης
Η κλάση ComparisonOptions σας επιτρέπει να ρυθμίσετε τη συμπεριφορά της διαδικασίας σύγκρισης, όπως η ενεργοποίηση streaming, ο καθορισμός ορίων μεγέθους αρχείων και η επιλογή μορφών εξόδου.
- Χρησιμοποιήστε streaming mode (
ComparisonOptions.setUseStreaming(true)). - Περιορίστε το μέγιστο μέγεθος αρχείου που επεξεργάζεται (
setMaxFileSize(200 * 1024 * 1024)για 200 MB). - Κλείστε ρητά το αντικείμενο
Comparisonμετά από κάθε εκτέλεση.
Στρατηγική επεξεργασίας σε παρτίδες
Διαιρέστε ένα τεράστιο δέντρο καταλόγου σε λογικές παρτίδες (π.χ. ανά μονάδα ή ανά χρονική περίοδο) και εκτελέστε κάθε παρτίδα διαδοχικά. Αυτό αποτρέπει το JVM από το να κρατάει περισσότερα από μία παρτίδες στη μνήμη ταυτόχρονα.
Παράλληλη επεξεργασία για ανεξάρτητους καταλόγους
Αν έχετε πολλαπλά ζεύγη καταλόγων προς σύγκριση (π.χ. νυχτερινές κατασκευές για διάφορα micro‑services), ξεκινήστε ξεχωριστές στιγμές Comparison σε ένα thread pool. Κάθε νήμα εργάζεται πάνω στο δικό του ζεύγος, αξιοποιώντας όλους τους πυρήνες CPU.
Πραγματικές περιπτώσεις χρήσης και βιομηχανικές εφαρμογές
Η σύγκριση καταλόγων δεν είναι μόνο εργαλείο προγραμματιστών — χρησιμοποιείται σε διάφορους κλάδους για κρίσιμες επιχειρησιακές διαδικασίες:
Ανάπτυξη λογισμικού και DevOps
Διαχείριση εκδόσεων: Συγκρίνετε φακέλους staging vs production πριν από την ανάπτυξη για να εντοπίσετε αποκλίσεις διαμόρφωσης. Η αναφορά HTML μπορεί να επισυναφθεί σε pull‑request για έλεγχο από ενδιαφερόμενους.
Χρηματοοικονομικός τομέας και συμμόρφωση
Διατήρηση αρχείου ελέγχου: Τα χρηματοπιστωτικά ιδρύματα χρησιμοποιούν τη σύγκριση καταλόγων για την παρακολούθηση αλλαγών εγγράφων ώστε να τηρούν τις κανονιστικές απαιτήσεις, διασφαλίζοντας ότι κάθε τροποποίηση καταγράφεται και αρχειοθετείται.
Διαχείριση δεδομένων και διαδικασίες ETL
Επαλήθευση ακεραιότητας δεδομένων: Μετά από μαζική μεταφορά δεδομένων, εκτελέστε σύγκριση φακέλων για να εγγυηθείτε ότι κάθε πηγαίο αρχείο έχει μεταφερθεί σωστά στον προορισμό.
Διαχείριση περιεχομένου και εκδόσεις
Έλεγχος εκδόσεων για μη‑τεχνικές ομάδες: Οι ομάδες μάρκετινγκ μπορούν να συγκρίνουν δύο εκδόσεις του φακέλου assets ενός ιστότοπου χωρίς γνώση Git, λαμβάνοντας μια σαφή οπτική diff.
Προχωρημένες συμβουλές και βέλτιστες πρακτικές
Αφού δουλέψατε με σύγκριση καταλόγων σε παραγωγικά περιβάλλοντα, ακολουθούν ορισμένα μαθήματα που μάθαμε με κόπο:
Logging και παρακολούθηση
Ενσωματώστε το SLF4J με έναν rolling file appender για να καταγράψετε χρόνο έναρξης, χρόνο λήξης, αριθμό επεξεργασμένων αρχείων και τυχόν εξαιρέσεις. Αυτό το log γίνεται ανεκτίμητο όταν ερευνάτε σποραδικά σφάλματα.
Ανάκτηση από σφάλματα και ανθεκτικότητα
Τυλίξτε την κλήση compare σε ένα μπλοκ retry που συλλαμβάνει προσωρινά σφάλματα I/O (π.χ. διακοπές δικτύου σε συνδεδεμένους δίσκους) και επαναλαμβάνει τη σύγκριση έως και τρεις φορές πριν αποτύχει.
Διαχείριση ρυθμίσεων
Εξωτερικεύστε όλες τις διαδρομές, μορφές εξόδου και σημαίες απόδοσης σε ένα αρχείο application.yml ή properties. Αυτό επιτρέπει στις ομάδες ops να ρυθμίζουν τις παραμέτρους χωρίς να χρειάζεται επαναμεταγλώττιση του JAR.
Διαχείριση διαδρομών ανεξάρτητα από πλατφόρμα
Κατασκευάστε πάντα διαδρομές με java.nio.file.Paths.get(...) και χρησιμοποιήστε File.separator όταν ενώνετε συμβολοσειρές. Έτσι αποφεύγετε σφάλματα κατά τη μετάβαση από Windows (\) σε Linux (/) περιβάλλοντα.
Παράβλεψη timestamps όταν δεν έχουν σημασία
Αν ενδιαφέρουν μόνο οι αλλαγές στο περιεχόμενο, ορίστε CompareOptions.setIgnoreMetadata(true). Αυτό αποτρέπει ψευδώς θετικά αποτελέσματα που προκύπτουν από αυτόματες ενημερώσεις timestamps σε αντιγραμμένα αρχεία.
Επίλυση κοινών προβλημάτων κατά την ανάπτυξη
Λειτουργεί στην ανάπτυξη, αποτυγχάνει στην παραγωγή
Άμεση απάντηση: Ελέγξτε τις διαφορές ευαισθησίας πεζών‑κεφαλαίων (Windows vs Linux), επαληθεύστε τα δικαιώματα του συστήματος αρχείων και αντικαταστήστε τους σκληρά κωδικοποιημένους διαχωριστές διαδρομών με File.separator.
Οι παραγωγικοί διακομιστές τρέχουν συχνά σε Linux, όπου myFile.txt και MyFile.txt θεωρούνται διαφορετικά. Χρησιμοποιήστε τις API Path για κανονικοποίηση πεζών‑κεφαλαίων και αποφυγή τυχαίων ασυμφωνιών.
Ασυνεπή αποτελέσματα
Άμεση απάντηση: Διασφαλίστε ότι κανένα εξωτερικό πρόγραμμα δεν τροποποιεί αρχεία κατά τη διάρκεια της σύγκρισης και ρυθμίστε το CompareOptions να αγνοεί timestamps αν προκαλούν ψευδείς διαφορές.
Η εκτέλεση της σύγκρισης σε ένα στιγμιότυπο μόνο για ανάγνωση (π.χ. mounted volume snapshot) εγγυάται καθοριστικά αποτελέσματα.
Συχνές ερωτήσεις
Ε: Πώς διαχειρίζομαι καταλόγους με εκατομμύρια αρχεία;
Α: Συνδυάστε επεξεργασία σε παρτίδες, αυξήστε το heap της JVM (-Xmx8g ή περισσότερο), ενεργοποιήστε τη λειτουργία streaming και τρέξτε συγκρίσεις υπο‑καταλόγων παράλληλα. Τα τμήματα Batch Processing Strategy και Parallel Processing παρέχουν έτοιμα πρότυπα.
Ε: Μπορώ να συγκρίνω καταλόγους που βρίσκονται σε διαφορετικούς διακομιστές;
Α: Ναι, αλλά η καθυστέρηση δικτύου κυριαρχεί στον χρόνο εκτέλεσης. Για βέλτιστη απόδοση, αντιγράψτε πρώτα τον απομακρυσμένο φάκελο τοπικά ή προσαρτήστε το απομακρυσμένο share με επαρκή εύρος ζώνης I/O πριν καλέσετε τη σύγκριση.
Ε: Ποιες μορφές αρχείων υποστηρίζει το GroupDocs.Comparison;
Α: Υποστηρίζει πάνω από 70 μορφές, συμπεριλαμβανομένων DOC/DOCX, PDF, PPT/PPTX, XLS/XLSX, TXT, HTML, XML, CSV και κοινών τύπων εικόνων (PNG, JPEG, BMP). Δείτε την επίσημη τεκμηρίωση για την πιο πρόσφατη λίστα.
Ε: Πώς μπορώ να ενσωματώσω αυτή τη σύγκριση σε pipeline CI/CD;
Α: Συσκευάστε τη λογική σύγκρισης σε εκτελέσιμο JAR ή Maven plugin, έπειτα καλέστε το ως βήμα build σε Jenkins, GitHub Actions, Azure Pipelines ή GitLab CI. Εξάγετε την αναφορά HTML ως artefact του build για επόμενη αξιολόγηση.
Ε: Μπορώ να προσαρμόσω την εμφάνιση της HTML αναφοράς;
Α: Το ενσωματωμένο HTML template είναι σταθερό, αλλά μπορείτε να κάνετε post‑processing του παραγόμενου αρχείου—να ενσωματώσετε προσαρμοσμένο CSS ή JavaScript—για να ταιριάζει με το εταιρικό branding ή να προσθέσετε διαδραστικά στοιχεία.
Τελευταία ενημέρωση: 2026-08-09
Δοκιμασμένο με: GroupDocs.Comparison 25.2 (Java)
Συγγραφέας: GroupDocs
<repositories>
<repository>
<id>repository.groupdocs.com</id>
<name>GroupDocs Repository</name>
<url>https://releases.groupdocs.com/comparison/java/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.groupdocs</groupId>
<artifactId>groupdocs-comparison</artifactId>
<version>25.2</version>
</dependency>
</dependencies>
import com.groupdocs.comparison.Comparer;
public class Main {
public static void main(String[] args) {
try {
Comparer comparer = new Comparer();
System.out.println("GroupDocs.Comparison initialized successfully!");
} catch (Exception e) {
System.err.println("Setup issue: " + e.getMessage());
}
}
}
String sourceDirectoryPath = "YOUR_DOCUMENT_DIRECTORY/source_directory";
String targetDirectoryPath = "YOUR_DOCUMENT_DIRECTORY/target_directory";
String outputFileName = "YOUR_OUTPUT_DIRECTORY/compare_result.html";
import com.groupdocs.comparison.options.CompareOptions;
import com.groupdocs.comparison.options.enums.FolderComparisonExtension;
CompareOptions compareOptions = new CompareOptions();
compareOptions.setDirectoryCompare(true);
compareOptions.setFolderComparisonExtension(FolderComparisonExtension.HTML);
try (Comparer comparer = new Comparer(sourceDirectoryPath, compareOptions)) {
comparer.add(targetDirectoryPath, compareOptions);
comparer.compareDirectory(outputFileName, compareOptions);
System.out.println("Directory comparison completed. Results saved to: " + outputFileName);
} catch (Exception e) {
System.err.println("Comparison failed: " + e.getMessage());
e.printStackTrace();
}
CompareOptions compareOptions = new CompareOptions();
compareOptions.setDirectoryCompare(true);
// HTML for human review
compareOptions.setFolderComparisonExtension(FolderComparisonExtension.HTML);
// Or PDF for formal reports
// compareOptions.setFolderComparisonExtension(FolderComparisonExtension.PDF);
CompareOptions compareOptions = new CompareOptions();
compareOptions.setDirectoryCompare(true);
// Skip temporary files and build directories
// Note: Exact filtering syntax may vary - check current API documentation
compareOptions.setShowDeletedContent(false); // Don't highlight deleted files
compareOptions.setShowInsertedContent(true); // Do highlight new files
// JVM args: -Xmx4g -Xms2g
// For very large directories, consider processing subdirectories separately
String[] subdirectories = {"subdir1", "subdir2", "subdir3"};
for (String subdir : subdirectories) {
String sourceSub = sourceDirectoryPath + "/" + subdir;
String targetSub = targetDirectoryPath + "/" + subdir;
// Process each subdirectory individually
}
// Better path handling
Path sourcePath = Paths.get(sourceDirectoryPath).toAbsolutePath();
Path targetPath = Paths.get(targetDirectoryPath).toAbsolutePath();
if (!Files.exists(sourcePath)) {
throw new IllegalArgumentException("Source directory doesn't exist: " + sourcePath);
}
if (!Files.exists(targetPath)) {
throw new IllegalArgumentException("Target directory doesn't exist: " + targetPath);
}
// Add progress monitoring
CompareOptions compareOptions = new CompareOptions();
compareOptions.setDirectoryCompare(true);
// Log progress (pseudo-code - actual implementation may vary)
long startTime = System.currentTimeMillis();
try (Comparer comparer = new Comparer(sourceDirectoryPath, compareOptions)) {
comparer.add(targetDirectoryPath, compareOptions);
comparer.compareDirectory(outputFileName, compareOptions);
long duration = System.currentTimeMillis() - startTime;
System.out.println("Comparison completed in: " + (duration / 1000) + " seconds");
}
// Increase heap size via JVM arguments
// -Xmx8g (for 8GB max heap)
// -XX:+UseG1GC (for better garbage collection with large heaps)
// In your code, help the GC by nulling large objects
CompareOptions compareOptions = new CompareOptions();
try (Comparer comparer = new Comparer(sourceDirectoryPath, compareOptions)) {
// ... do comparison
comparer.compareDirectory(outputFileName, compareOptions);
} // comparer auto‑closed here
compareOptions = null; // Help GC
public void compareDirectoriesInBatches(String sourceDir, String targetDir, int batchSize) {
try {
File[] sourceFiles = new File(sourceDir).listFiles();
if (sourceFiles != null) {
for (int i = 0; i < sourceFiles.length; i += batchSize) {
int end = Math.min(i + batchSize, sourceFiles.length);
processBatch(sourceFiles, i, end, targetDir);
// Optional: pause between batches to prevent system overload
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Batch processing interrupted", e);
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
ExecutorService executor = Executors.newFixedThreadPool(4);
List<Future<String>> futures = new ArrayList<>();
for (DirectoryPair pair : directoryPairs) {
Future<String> future = executor.submit(() -> {
// Perform comparison for this pair
return compareDirectoryPair(pair.source, pair.target);
});
futures.add(future);
}
// Wait for all comparisons to complete
for (Future<String> future : futures) {
try {
String result = future.get();
System.out.println("Comparison result: " + result);
} catch (Exception e) {
System.err.println("Comparison failed: " + e.getMessage());
}
}
executor.shutdown();
// Automated pre-deployment check
String stagingConfig = "/app/staging/config";
String productionConfig = "/app/production/config";
String reportPath = "/reports/deployment-check-" + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE) + ".html";
CompareOptions options = new CompareOptions();
options.setDirectoryCompare(true);
options.setFolderComparisonExtension(FolderComparisonExtension.HTML);
try (Comparer comparer = new Comparer(stagingConfig, options)) {
comparer.add(productionConfig, options);
comparer.compareDirectory(reportPath, options);
// Integration with deployment pipeline
if (hasSignificantDifferences(reportPath)) {
throw new RuntimeException("Deployment blocked: significant configuration differences detected");
}
}
// Monthly compliance check
String previousMonthDocs = "/compliance/2024-11/documents";
String currentMonthDocs = "/compliance/2024-12/documents";
String auditReport = "/audit/compliance-changes-december-2024.html";
// Compare and generate audit‑ready reports
performComplianceComparison(previousMonthDocs, currentMonthDocs, auditReport);
public boolean verifyDataMigration(String sourceDataDir, String migratedDataDir) {
try {
CompareOptions options = new CompareOptions();
options.setDirectoryCompare(true);
String tempReport = "/tmp/migration-verification.html";
try (Comparer comparer = new Comparer(sourceDataDir, options)) {
comparer.add(migratedDataDir, options);
comparer.compareDirectory(tempReport, options);
}
// Custom logic to parse results and determine if migration was successful
return analyzeComparisonResults(tempReport);
} catch (Exception e) {
System.err.println("Migration verification failed: " + e.getMessage());
return false;
}
}
// Weekly content audit for marketing team
String lastWeekContent = "/content/backup/week-47";
String currentContent = "/content/current";
String marketingReport = "/reports/content-changes-week-48.html";
CompareOptions options = new CompareOptions();
options.setDirectoryCompare(true);
options.setFolderComparisonExtension(FolderComparisonExtension.HTML);
// Generate human‑readable report for non‑technical stakeholders
generateContentChangeReport(lastWeekContent, currentContent, marketingReport, options);
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(DirectoryComparer.class);
public void compareWithLogging(String source, String target, String output) {
logger.info("Starting directory comparison: {} vs {}", source, target);
long startTime = System.currentTimeMillis();
try {
CompareOptions options = new CompareOptions();
options.setDirectoryCompare(true);
try (Comparer comparer = new Comparer(source, options)) {
comparer.add(target, options);
comparer.compareDirectory(output, options);
}
long duration = System.currentTimeMillis() - startTime;
logger.info("Comparison completed successfully in {}ms. Report: {}", duration, output);
} catch (Exception e) {
logger.error("Directory comparison failed for {} vs {}: {}", source, target, e.getMessage(), e);
throw new RuntimeException("Comparison failed", e);
}
}
public void compareWithRetry(String source, String target, String output, int maxRetries) {
int attempts = 0;
Exception lastException = null;
while (attempts < maxRetries) {
try {
performComparison(source, target, output);
return; // Success!
} catch (Exception e) {
lastException = e;
attempts++;
if (attempts < maxRetries) {
try {
Thread.sleep(1000 * attempts); // Exponential backoff
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Retry interrupted", ie);
}
}
}
}
throw new RuntimeException("Comparison failed after " + maxRetries + " attempts", lastException);
}
// application.properties
comparison.output.format=HTML
comparison.max.retries=3
comparison.batch.size=100
comparison.parallel.threads=4
// In your code
@Value("${comparison.output.format:HTML}")
private String outputFormat;
@Value("${comparison.max.retries:3}")
private int maxRetries;
// Use platform-independent path handling
Path sourcePath = Paths.get(sourceDirectory);
Path targetPath = Paths.get(targetDirectory);
Path outputPath = Paths.get(outputDirectory);
// Validate permissions before starting
if (!Files.isReadable(sourcePath)) {
throw new IllegalStateException("Cannot read source directory: " + sourcePath);
}
if (!Files.isReadable(targetPath)) {
throw new IllegalStateException("Cannot read target directory: " + targetPath);
}
if (!Files.isWritable(outputPath.getParent())) {
throw new IllegalStateException("Cannot write to output directory: " + outputPath.getParent());
}
CompareOptions options = new CompareOptions();
options.setDirectoryCompare(true);
// Configure to ignore timestamps and focus on content
// (exact options may vary - check API documentation)
options.setIgnoreWhitespaces(true);
options.setIgnoreFormatting(true);