Une simple bibliothèque Java pour comparer deux fichiers PDF. Les fichiers sont rendus et comparés pixel par pixel. Il n'y a pas de comparaison de texte.
Incluez-le simplement comme dépendance. Veuillez vérifier la version la plus récente disponible :
< dependencies >
< dependency >
< groupId >de.redsix</ groupId >
< artifactId >pdfcompare</ artifactId >
< version >...</ version > <!-- see current version in the maven central tag above -->
</ dependency >
</ dependencies >
Il existe une interface utilisateur interactive simple, lorsque vous démarrez le fichier jar sans aucun argument supplémentaire (qui démarre la classe de.redsix.pdfcompare.Main). Il vous permet de choisir les fichiers à comparer et également de marquer les zones à ignorer et de les écrire dans un fichier ignoré.
À côté de l'interface utilisateur, vous pouvez fournir un fichier attendu et réel ainsi qu'un paramètre supplémentaire via une CLI. Pour obtenir une aide pour la CLI, utilisez l'option -h ou --help-.
usage: java -jar pdfcompare-x.x.x-full.jar [EXPECTED] [ACTUAL]
-h,--help Displays this text and exit
...
Mais PdfCompare se concentre sur l’utilisation intégrée en tant que bibliothèque.
new PdfComparator ( "expected.pdf" , "actual.pdf" ). compare (). writeTo ( "diffOutput" );
Cela produira un PDF de sortie pouvant inclure des marquages pour les différences trouvées. PdfCompare restitue une page du fichier pdf attendu et la même page du fichier pdf réel en une image bitmap et compare ces deux images pixel par pixel. Les pixels égaux sont un peu estompés. Les pixels différents sont marqués en rouge et vert. Vert pour les pixels qui se trouvaient dans le fichier pdf attendu, mais qui ne sont pas présents dans le fichier pdf réel. Rouge pour les pixels présents dans le fichier.pdf réel, mais qui n'étaient pas dans le.pdf attendu. Et il y a des marquages magenta sur le bord du papier pour trouver rapidement les zones qui diffèrent. Les zones ignorées sont marquées d’un fond jaune. Les pages attendues mais non arrivées sont marquées d'une bordure rouge. Les pages qui apparaissent mais qui n'étaient pas attendues sont marquées d'une bordure verte.
La méthode compare renvoie un CompareResult, qui peut être interrogé :
final CompareResult result = new PdfComparator ( "expected.pdf" , "actual.pdf" ). compare ();
if ( result . isNotEqual ()) {
System . out . println ( "Differences found!" );
}
if ( result . isEqual ()) {
System . out . println ( "No Differences found!" );
}
if ( result . hasDifferenceInExclusion ()) {
System . out . println ( "Differences in excluded areas found!" );
}
result . getDifferences (); // returns page areas, where differences were found
Pour plus de commodité, writeTo renvoie également le statut égal :
boolean isEquals = new PdfComparator ( "expected.pdf" , "actual.pdf" ). compare (). writeTo ( "diffOutput" );
if (! isEquals ) {
System . out . println ( "Differences found!" );
}
La méthode de comparaison peut être appelée avec des noms de fichiers tels que Strings, Files, Paths ou InputStreams.
Il est également possible de définir des zones rectangulaires qui seront ignorées lors de la comparaison. Pour cela, il faut créer un fichier qui définit les zones à ignorer. Le format de fichier est JSON (ou en fait un sur-ensemble appelé HOCON) et a la forme suivante :
exclusions: [
{
page : 2
x1 : 300 // entries without a unit are in pixels. Pdfs are rendered by default at 300DPI
y1 : 1000
x2 : 550
y2 : 1300
} ,
{
// page is optional. When not given, the exclusion applies to all pages.
x1 : 130.5 mm // entries can also be given in units of cm, mm or pt (DTP-Point defined as 1/72 Inches)
y1 : 3.3 cm
x2 : 190 mm
y2 : 3.7 cm
} ,
{
page : 7
// coordinates are optional. When not given, the whole page is excluded.
}
]
Lorsque le fichier d'exclusion fourni est introuvable, il est ignoré et la comparaison est effectuée sans les exclusions.
Les exclusions sont prévues dans le code comme suit :
new PdfComparator ( "expected.pdf" , "actual.pdf" ). withIgnore ( "ignore.conf" ). compare ();
Alternativement, une exclusion peut être ajoutée via l'API comme suit :
new PdfComparator ( "expected.pdf" , "actual.pdf" )
. withIgnore ( new PageArea ( 1 , 230 , 350 , 450 , 420 ))
. withIgnore ( new PageArea ( 2 ))
. compare ();
Lorsque vous souhaitez comparer des fichiers PDF protégés par mot de passe, vous pouvez donner le mot de passe au comparateur via les méthodes withExpectedPassword (String password) ou withActualPassword (String password), respectivement.
new PdfComparator ( "expected.pdf" , "actual.pdf" )
. withExpectedPassword ( "somePwd" )
. withActualPassword ( "anotherPwd" )
. compare ();
PdfCompare peut être configuré avec un fichier de configuration. Le fichier de configuration par défaut s'appelle "application.conf" et il doit être situé à la racine du chemin de classe.
PdfCompare utilise Lightbend Config (anciennement appelé TypeSafe Config) pour lire ses fichiers de configuration. Si vous souhaitez spécifier un autre fichier de configuration, vous pouvez en savoir plus ici : https://github.com/lightbend/config#standard-behavior. En particulier, vous pouvez spécifier un fichier de configuration de remplacement avec l'argument de ligne de commande -Dconfig.file=path/to/file.
Vous pouvez également spécifier des paramètres via des variables d'environnement système ou en tant que paramètre Jvm avec -DvariableName=
Une autre façon de spécifier un emplacement de configuration différent par programme consiste à créer un nouveau ConfigFileEnvironment(...) et à le transmettre à PdfCompare.withEnvironment(...).
Tous les paramètres qui peuvent être modifiés via le fichier application.conf peuvent également être modifiés par programme via l'API. Pour ce faire, vous pouvez utiliser le code suivant :
new PdfComparator ( "expected.pdf" , "actual.pdf" )
. withEnvironment ( new SimpleEnvironment ()
. setActualColor ( Color . green )
. setExpectedColor ( Color . blue ))
. compare ();
Le SimpleEnvironment délègue tous les paramètres qui n’ont pas été attribués à l’environnement par défaut.
Grâce à l'environnement, vous pouvez configurer les paramètres de mémoire (voir ci-dessus) et les paramètres suivants :
PPP = 300
Définit le DPI avec lequel les pages PDF sont rendues. La valeur par défaut est 300.
Couleur attendue = 00B400 (VERT)
La couleur attendue est la couleur utilisée pour les pixels attendus, mais qui ne sont pas là. Les couleurs sont spécifiées au format HTML-Style (sans le « # » initial) : les deux premiers caractères définissent la partie rouge de la couleur en hexadécimal. Les deux caractères suivants définissent la partie verte de la couleur. Les deux derniers caractères définissent la partie bleue de la couleur à utiliser.
couleur réelle = D20000 (ROUGE)
La couleur réelle est la couleur utilisée pour les pixels présents, mais non attendus. Les couleurs sont spécifiées au format HTML-Style (sans le « # » initial) : les deux premiers caractères définissent la partie rouge de la couleur en hexadécimal. Les deux caractères suivants définissent la partie verte de la couleur. Les deux derniers caractères définissent la partie bleue de la couleur à utiliser.
tempDir=System.property("java.io.tmpdir")
Définit le répertoire dans lequel écrire les fichiers temporaires. La valeur par défaut est la valeur Java par défaut pour java.io.tmpdir, qui détermine généralement une valeur par défaut spécifique au système, comme /tmp sur la plupart des systèmes Unix.
AllowedDifferenceInPercentPerPage=0,2
Pourcentage de pixels pouvant différer par page. La valeur par défaut est 0. Si pour une raison quelconque votre rendu est un peu erroné ou si vous autorisez une certaine marge d'erreur, vous pouvez configurer un pourcentage de pixels ignorés lors de la comparaison. De cette façon, une différence n'est signalée que lorsque la différence dépasse le pourcentage de pixels donné. Le pourcentage est calculé par page. Non pas que les différences soient toujours marquées dans le fichier de sortie, lorsque vous ajoutezEqualPagesToResult.
traitement parallèle = vrai
Lorsqu'il est défini sur false, désactive tout traitement parallèle et traite tout dans un seul thread.
addEqualPagesToResult=true
Lorsqu'il est défini sur false, seules les pages présentant des différences sont ajoutées au résultat et constituent le document PDF de différence résultant.
failOnMissingIgnoreFile = faux
Lorsqu'il est défini sur true, un fichier ignoré manquant entraîne une exception. Sinon, il est ignoré et seuls des messages de journal de niveau information sont écrits.
Il existe quelques implémentations différentes de CompareResults avec des caractéristiques différentes. Le peut être utilisé pour contrôler certains aspects du comportement du système, notamment la consommation de mémoire.
Il est bon de connaître quelques éléments internes lors de l’utilisation de PdfCompare. Voici en un mot ce que fait PdfCompare lorsqu'il compare deux PDF.
PdfCompare utilise la bibliothèque Apache PdfBox pour lire et écrire des PDF.
Ainsi, comparer de gros fichiers PDF peut utiliser beaucoup de mémoire. Je n'ai pas encore trouvé de moyen d'écrire la différence Pdf page par page de manière incrémentielle avec PdfBox, mais il existe quelques solutions de contournement.
Il existe actuellement deux CompareResults différents, qui ont des stratégies différentes pour échanger des pages sur le disque et limiter ainsi la consommation de mémoire.
Une implémentation différente de CompareResult peut être utilisée comme suit :
new PdfComparator ( "expected.pdf" , "actual.pdf" , new CompareResultWithPageOverflow ()). compare ();
Il existe également certains paramètres internes de limites de mémoire qui peuvent être modifiés. Ajoutez simplement un fichier appelé "application.conf" à la racine du chemin de classe. Ce fichier peut avoir tout ou partie des paramètres suivants pour remplacer les valeurs par défaut indiquées ici :
imageCacheSizeCount = 30
Combien d'images sont mises en cache par PdfBox
maxImageSizeInCache = 100 000
Une taille maximale approximative des images mises en cache, pour empêcher la mise en cache de très grandes images
mergeCacheSizeMB = 100
Lorsque les fichiers PDF sont partiellement écrits puis fusionnés, il s'agit du cache mémoire configuré pour l'instance PdfBox qui effectue la fusion.
swapCacheSizeMB = 100
Lorsque les fichiers PDF sont partiellement écrits, il s'agit du cache mémoire configuré pour l'instance PdfBox qui effectue les écritures partielles.
documentCacheSizeMo=200
Il s'agit de la taille du cache configurée pour l'instance PdfBox, qui charge les documents comparés.
traitement parallèle = vrai
Lorsqu'il est défini sur false, désactive tout traitement parallèle et traite tout dans un seul thread.
globalTimeoutInMinutes=15
Définissez le délai d'attente global. Il s’agit d’une mesure de sécurité permettant de détecter d’éventuels blocages. Les comparaisons complexes peuvent prendre plus de temps, il faudra donc peut-être augmenter cette valeur.
exécuteurTimeoutInSeconds=60
Définit le délai d'attente pour que les exécuteurs terminent une fois que le délai global a été atteint. Il est peu probable que vous ayez besoin de changer cela.
Ainsi, dans cette configuration par défaut, PdfBox devrait utiliser jusqu'à 400 Mo de RAM pour ses caches, avant de passer au disque. J'ai une bonne expérience dans l'octroi d'un espace de mémoire de 2 Go à la JVM.
Un grand merci à Chethan Rao [email protected] pour m'avoir aidé à diagnostiquer les problèmes de mémoire insuffisante et m'avoir proposé l'idée d'écritures partielles et de fusion des PDF générés.