Passer au contenu du pied de page
VIDéOS

Comment écrire des BarCodes Unicode et en langues internationales en C# | IronPDF

Migrer de ZXing.Net vers IronBarcode

Ce guide décrit la migration complète de ZXing .NET vers Code-barres IronBarcode pour les applications .NET qui lisent et génèrent des codes-barres. Il aborde la suppression du package principal de ZXing.Net et des packages de liaison, l'élimination des contournements de PdfiumViewer là où ils sont présents, et le remplacement de chaque instanciation d'BarcodeReader avec l'API statique d'IronBarcode. Chaque section comprend des exemples de code avant et après, tirés des modèles les plus couramment utilisés dans les intégrations ZXing .NET .

Pourquoi migrer depuis ZXing .NET ?

ZXing .NET a rendu de précieux services à la communauté .NET pendant plus d'une décennie en tant que bibliothèque de codes-barres gratuite sous Apache 2.0. Cependant, plusieurs contraintes architecturales se transforment en coûts opérationnels à mesure que les applications gagnent en envergure ou en complexité.

Propriété de la sécurité des threads : L'BarcodeReader de ZXing.Net est un objet avec état. La documentation de la bibliothèque elle-même indique que les instances ne doivent pas être partagées entre les threads. En pratique, cela signifie que chaque chemin de traitement concurrent — chaque action de contrôleur gérant des requêtes simultanées, chaque tâche d'un lot parallèle — doit allouer, configurer et supprimer son propre lecteur. À mesure que le volume des requêtes augmente, ce modèle d'allocation engendre une pression mesurable sur la mémoire. L'alternative ThreadLocal<BarcodeReader> réduit la fréquence d'allocation mais introduit sa propre complexité de désallocation. Dans les deux cas, la correction en cas de concurrence est le problème de l'appelant, et non une garantie fournie par la bibliothèque.

Risque de spécification de format : ZXing.Net nécessite que l'reader.Options.PossibleFormats soit rempli avant chaque opération de décodage. Un code-barres dans un format non présent dans cette liste renvoie null — pas d'exception, pas d'avertissement, pas d'indication qu'un code-barres était présent mais non reconnu. Pour les applications qui reçoivent des documents de partenaires externes, ce comportement silencieusement raté est un risque de fiabilité : une commande mal expédiée, un enregistrement de patient raté, ou une entrée d'audit qui ne s'écrit jamais peut tous provenir d'une liste de formats configurée pour une exigence précédente et jamais mise à jour.

Lacune en matière de traitement PDF : ZXing .NET ne lit que les images bitmap. Lorsque les documents sources sont des PDF (factures, manifestes d'expédition, certificats de conformité), les appelants doivent intégrer une bibliothèque de rendu PDF distincte (PdfiumViewer étant la plus courante), implémenter une boucle d'énumération des pages, configurer le DPI, gérer les fichiers temporaires et gérer le nettoyage en cas de succès ou d'échec. Il s'agit de 30 à 50 lignes de code d'infrastructure par intégration qui existent uniquement pour convertir ce que ZXing .NET ne peut pas lire (PDF) en ce qu'il peut (images bitmap). Cette infrastructure possède ses propres dépendances, ses propres exigences de déploiement et ses propres modes de défaillance.

Fragmentation de la liaison de plateforme : la capacité de chargement d'images de ZXing.Net est répartie entre des packages de liaison spécifiques à chaque plateforme. La liaison Windows utilise System.Drawing.Bitmap; la liaison multiplateforme utilise SixLabors.ImageSharp avec un paramètre de type générique différent et une directive using différente. Un projet qui commence sur Windows et qui est plus tard containerisé sur Linux doit changer ses références NuGet et son code de chargement d'image. Deux chemins d'exécution pour une même opération augmentent la surface d'apparition de bogues et compliquent les modifications futures de la couche de numérisation.

Le problème fondamental

L'illustration la plus claire de l'architecture ZXing .NET est l'écart entre un appel monothread et un appel concurrent. Dans ZXing .NET, le traitement concurrent nécessite la création d'un objet lecteur complet pour chaque opération parallèle :

// ZXing.Net: full reader instantiation and configuration on every parallel task
Parallel.ForEach(files, file =>
{
    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.EAN_13
    };

    using var bitmap = new Bitmap(file);
    var result = reader.Decode(bitmap);
    if (result != null)
        processed[file] = result.Text;
});
// ZXing.Net: full reader instantiation and configuration on every parallel task
Parallel.ForEach(files, file =>
{
    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.EAN_13
    };

    using var bitmap = new Bitmap(file);
    var result = reader.Decode(bitmap);
    if (result != null)
        processed[file] = result.Text;
});
Imports ZXing
Imports System.Drawing
Imports System.Threading.Tasks

Parallel.ForEach(files, Sub(file)
    Dim reader As New BarcodeReader()
    reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.EAN_13
    }

    Using bitmap As New Bitmap(file)
        Dim result = reader.Decode(bitmap)
        If result IsNot Nothing Then
            processed(file) = result.Text
        End If
    End Using
End Sub)
$vbLabelText   $csharpLabel

IronBarcode supprime entièrement l'objet. L'appel statique est identique, qu'il s'exécute sur un seul thread ou sur une centaine :

// IronBarcode: static call, same code for single-threaded and concurrent use
Parallel.ForEach(files, file =>
{
    var result = BarcodeReader.Read(file).FirstOrDefault();
    if (result != null)
        processed[file] = result.Value;
});
// IronBarcode: static call, same code for single-threaded and concurrent use
Parallel.ForEach(files, file =>
{
    var result = BarcodeReader.Read(file).FirstOrDefault();
    if (result != null)
        processed[file] = result.Value;
});
Imports IronBarCode
Imports System.Threading.Tasks

Parallel.ForEach(files, Sub(file)
    Dim result = BarcodeReader.Read(file).FirstOrDefault()
    If result IsNot Nothing Then
        processed(file) = result.Value
    End If
End Sub)
$vbLabelText   $csharpLabel

Comparaison des fonctionnalités : Code-barres IronBarcode vs ZXing .NET

Fonction ZXing.Net Code-barres IronBarcode
Licence Apache 2.0 (gratuit) Commercial
Sécurité des threads Non thread-safe — une nouvelle instance par thread est requise. API statique sécurisée pour les threads
Détection de format Manuel — liste PossibleFormats requise Automatique — Plus de 50 formats
Lecture de PDF Non — nécessite PdfiumViewer ou un logiciel similaire Natif — appel de méthode unique
Support de la plateforme Des packages de liaison distincts par plateforme Un seul package, toutes plateformes
Plusieurs codes-barres par image Oui — DecodeMultiple Oui — comportement par défaut
Génération de codes-barres Retourne Bitmap, nécessite un enregistrement manuel API fluide avec sortie intégrée
Prise en charge des logos QR Code Non Oui
Contrôle des couleurs du code QR Non Oui
Récupération de codes-barres endommagés drapeau TryHarder Correction d'images basée sur l'apprentissage automatique
Dépendances supplémentaires de Docker Peut nécessiter libgdiplus None
Assistance SLA commerciale Non Oui
Packages NuGet requis 2–3 (noyau + liaison + ImageSharp optionnel) 1

Démarrage rapide

Étape 1 : Supprimer les packages ZXing .NET

Supprimez tous les packages ZXing .NET et associés du projet :

dotnet remove package ZXing.Net
dotnet remove package ZXing.Net.Bindings.Windows.Compatibility
dotnet remove package ZXing.Net.Bindings.ImageSharp
dotnet remove package PdfiumViewer
dotnet remove package ZXing.Net
dotnet remove package ZXing.Net.Bindings.Windows.Compatibility
dotnet remove package ZXing.Net.Bindings.ImageSharp
dotnet remove package PdfiumViewer
SHELL

Si les binaires natifs de PdfiumViewer étaient installés en tant que paquet séparé :

dotnet remove package PdfiumViewer.Native.x64.v8-xfa
dotnet remove package PdfiumViewer.Native.x64.v8-xfa
SHELL

Si le Dockerfile contient apt-get install -y libgdiplus — ajouté pour supporter System.Drawing via la liaison Windows sur Linux — cette ligne peut être supprimée après la migration.

Étape 2 : Installer IronBarcode

dotnet add package IronBarcode
dotnet add package IronBarcode
SHELL

Aucun package de liaison supplémentaire ni dépendance spécifique à la plateforme n'est requis. Le même package NuGet fonctionne sous Windows, Linux, macOS et dans les conteneurs Docker. Pour plus de détails sur le déploiement, le guide d'installation d' Code-barres IronBarcode pour Docker et Linux détaille le modèle exact de Dockerfile.

Étape 3 : Mise à jour des espaces de noms et initialisation de la licence

Supprimez tous les espaces de noms liés à ZXing de chaque fichier utilisant des opérations de code-barres :

// Remove all of these:
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using ZXing.ImageSharp;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using PdfiumViewer;

// Add this single import:
using IronBarCode;
// Remove all of these:
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using ZXing.ImageSharp;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using PdfiumViewer;

// Add this single import:
using IronBarCode;
Imports IronBarCode
$vbLabelText   $csharpLabel

Ajouter l'initialisation de la licence au démarrage de l'application, avant toute opération sur les codes-barres :

// Program.cs or Startup.cs — initialise once at startup
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
// Program.cs or Startup.cs — initialise once at startup
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
' Program.vb or Startup.vb — initialise once at startup
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

La clé de licence est une chaîne simple qui peut être chargée à partir d'une variable d'environnement, appsettings.json, ou d'un gestionnaire de secrets. Aucun fichier à localiser, aucun chemin à configurer.

Exemples de migration de code

Lecture d'un seul code-barres à partir d'une image

Cet exemple remplace le modèle d'utilisation le plus courant de ZXing .NET : instancier un lecteur, configurer la liste des formats, charger une image bitmap et décoder.

Approche ZXing .NET :

using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;

public string ReadSingleBarcode(string imagePath)
{
    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.EAN_13
    };

    using var bitmap = new Bitmap(imagePath);
    var result = reader.Decode(bitmap);

    return result?.Text ?? string.Empty;
}
using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;

public string ReadSingleBarcode(string imagePath)
{
    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.EAN_13
    };

    using var bitmap = new Bitmap(imagePath);
    var result = reader.Decode(bitmap);

    return result?.Text ?? string.Empty;
}
Imports ZXing
Imports ZXing.Windows.Compatibility
Imports System.Drawing

Public Function ReadSingleBarcode(imagePath As String) As String
    Dim reader = New BarcodeReader()
    reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.EAN_13
    }

    Using bitmap As New Bitmap(imagePath)
        Dim result = reader.Decode(bitmap)
        Return If(result?.Text, String.Empty)
    End Using
End Function
$vbLabelText   $csharpLabel

Approche IronBarcode :

using IronBarCode;

public string ReadSingleBarcode(string imagePath)
{
    var result = BarcodeReader.Read(imagePath).FirstOrDefault();
    return result?.Value ?? string.Empty;
}
using IronBarCode;

public string ReadSingleBarcode(string imagePath)
{
    var result = BarcodeReader.Read(imagePath).FirstOrDefault();
    return result?.Value ?? string.Empty;
}
Imports IronBarCode

Public Function ReadSingleBarcode(imagePath As String) As String
    Dim result = BarcodeReader.Read(imagePath).FirstOrDefault()
    Return If(result?.Value, String.Empty)
End Function
$vbLabelText   $csharpLabel

La liste de formats, l'allocation Bitmap et le bloc using sont tous supprimés. Code-barres IronBarcode accepte directement un chemin de fichier et détecte automatiquement tous les formats pris en charge. La propriété qui renvoyait auparavant la chaîne décodée était result.Text dans ZXing.Net; elle est result.Value dans IronBarcode.

Lecture de tous les codes-barres à partir d'une image

Cet exemple remplace DecodeMultiple, qui dans ZXing.Net nécessite une liste de formats exhaustive pour éviter les manques silencieux.

Approche ZXing .NET :

using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;

public List<string> ReadAllBarcodes(string imagePath)
{
    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.CODE_39,
        BarcodeFormat.EAN_13,
        BarcodeFormat.EAN_8,
        BarcodeFormat.UPC_A,
        BarcodeFormat.DATA_MATRIX,
        BarcodeFormat.PDF_417
    };
    reader.Options.TryHarder = true;

    using var bitmap = new Bitmap(imagePath);
    var results = reader.DecodeMultiple(bitmap);

    return results?.Select(r => r.Text).ToList() ?? new List<string>();
}
using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;

public List<string> ReadAllBarcodes(string imagePath)
{
    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.CODE_39,
        BarcodeFormat.EAN_13,
        BarcodeFormat.EAN_8,
        BarcodeFormat.UPC_A,
        BarcodeFormat.DATA_MATRIX,
        BarcodeFormat.PDF_417
    };
    reader.Options.TryHarder = true;

    using var bitmap = new Bitmap(imagePath);
    var results = reader.DecodeMultiple(bitmap);

    return results?.Select(r => r.Text).ToList() ?? new List<string>();
}
Imports ZXing
Imports ZXing.Windows.Compatibility
Imports System.Drawing

Public Function ReadAllBarcodes(imagePath As String) As List(Of String)
    Dim reader = New BarcodeReader()
    reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.CODE_39,
        BarcodeFormat.EAN_13,
        BarcodeFormat.EAN_8,
        BarcodeFormat.UPC_A,
        BarcodeFormat.DATA_MATRIX,
        BarcodeFormat.PDF_417
    }
    reader.Options.TryHarder = True

    Using bitmap As New Bitmap(imagePath)
        Dim results = reader.DecodeMultiple(bitmap)
        Return If(results?.Select(Function(r) r.Text).ToList(), New List(Of String)())
    End Using
End Function
$vbLabelText   $csharpLabel

Approche IronBarcode :

using IronBarCode;

public List<string> ReadAllBarcodes(string imagePath)
{
    return BarcodeReader.Read(imagePath)
        .Select(r => r.Value)
        .ToList();
}
using IronBarCode;

public List<string> ReadAllBarcodes(string imagePath)
{
    return BarcodeReader.Read(imagePath)
        .Select(r => r.Value)
        .ToList();
}
Imports IronBarCode

Public Function ReadAllBarcodes(imagePath As String) As List(Of String)
    Return BarcodeReader.Read(imagePath) _
        .Select(Function(r) r.Value) _
        .ToList()
End Function
$vbLabelText   $csharpLabel

BarcodeReader.Read renvoie toujours une collection et ne renvoie jamais null, éliminant ainsi la garde de null sur le résultat. Pour ajuster l'équilibre précision-vitesse, consultez le guide des options de vitesse de lecture, qui couvre l'énumération ReadingSpeed sans restreindre la portée du format.

Traitement par lots simultané

Cet exemple illustre le plus directement la différence en matière de sécurité des threads. ZXing .NET nécessite un nouveau lecteur pour chaque opération parallèle ; Code-barres IronBarcode utilise le même appel statique quel que soit le niveau de concurrence.

Approche ZXing .NET :

using ZXing;
using ZXing.Windows.Compatibility;
using System.Collections.Concurrent;
using System.Drawing;

public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
    var output = new ConcurrentDictionary<string, string>();

    Parallel.ForEach(filePaths, new ParallelOptions { MaxDegreeOfParallelism = 4 }, file =>
    {
        // ZXing.Net is not thread-safe — a new reader is required per parallel operation
        var reader = new BarcodeReader();
        reader.Options.PossibleFormats = new List<BarcodeFormat>
        {
            BarcodeFormat.QR_CODE,
            BarcodeFormat.CODE_128
        };

        using var bitmap = new Bitmap(file);
        var result = reader.Decode(bitmap);
        if (result != null)
            output[file] = result.Text;
    });

    return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
using ZXing;
using ZXing.Windows.Compatibility;
using System.Collections.Concurrent;
using System.Drawing;

public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
    var output = new ConcurrentDictionary<string, string>();

    Parallel.ForEach(filePaths, new ParallelOptions { MaxDegreeOfParallelism = 4 }, file =>
    {
        // ZXing.Net is not thread-safe — a new reader is required per parallel operation
        var reader = new BarcodeReader();
        reader.Options.PossibleFormats = new List<BarcodeFormat>
        {
            BarcodeFormat.QR_CODE,
            BarcodeFormat.CODE_128
        };

        using var bitmap = new Bitmap(file);
        var result = reader.Decode(bitmap);
        if (result != null)
            output[file] = result.Text;
    });

    return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
Imports ZXing
Imports ZXing.Windows.Compatibility
Imports System.Collections.Concurrent
Imports System.Drawing

Public Function ProcessBatch(filePaths As IEnumerable(Of String)) As Dictionary(Of String, String)
    Dim output = New ConcurrentDictionary(Of String, String)()

    Parallel.ForEach(filePaths, New ParallelOptions With {.MaxDegreeOfParallelism = 4}, Sub(file)
        ' ZXing.Net is not thread-safe — a new reader is required per parallel operation
        Dim reader = New BarcodeReader()
        reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
            BarcodeFormat.QR_CODE,
            BarcodeFormat.CODE_128
        }

        Using bitmap As New Bitmap(file)
            Dim result = reader.Decode(bitmap)
            If result IsNot Nothing Then
                output(file) = result.Text
            End If
        End Using
    End Sub)

    Return output.ToDictionary(Function(kvp) kvp.Key, Function(kvp) kvp.Value)
End Function
$vbLabelText   $csharpLabel

Approche IronBarcode :

using IronBarCode;
using System.Collections.Concurrent;

public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
    var output = new ConcurrentDictionary<string, string>();
    var options = new BarcodeReaderOptions { MaxParallelThreads = 4 };

    Parallel.ForEach(filePaths, file =>
    {
        var result = BarcodeReader.Read(file, options).FirstOrDefault();
        if (result != null)
            output[file] = result.Value;
    });

    return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
using IronBarCode;
using System.Collections.Concurrent;

public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
    var output = new ConcurrentDictionary<string, string>();
    var options = new BarcodeReaderOptions { MaxParallelThreads = 4 };

    Parallel.ForEach(filePaths, file =>
    {
        var result = BarcodeReader.Read(file, options).FirstOrDefault();
        if (result != null)
            output[file] = result.Value;
    });

    return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
Imports IronBarCode
Imports System.Collections.Concurrent

Public Function ProcessBatch(filePaths As IEnumerable(Of String)) As Dictionary(Of String, String)
    Dim output = New ConcurrentDictionary(Of String, String)()
    Dim options = New BarcodeReaderOptions With {.MaxParallelThreads = 4}

    Parallel.ForEach(filePaths, Sub(file)
        Dim result = BarcodeReader.Read(file, options).FirstOrDefault()
        If result IsNot Nothing Then
            output(file) = result.Value
        End If
    End Sub)

    Return output.ToDictionary(Function(kvp) kvp.Key, Function(kvp) kvp.Value)
End Function
$vbLabelText   $csharpLabel

Il n'existe aucune instance de lecteur à protéger ou à isoler. Pour les modèles de pipeline asynchrones et la configuration du nombre de threads, consultez le guide de lecture de codes-barres asynchrones et multithreadés .

Extraction des codes-barres d'un PDF

Cet exemple remplace la boucle de rendu PdfiumViewer. Si l'intégration existante utilisait Ghostscript ou iText au lieu de PdfiumViewer, le bloc avant aura un aspect différent en détail mais structurellement identique : une boucle d'énumération de pages alimentant des bitmaps à ZXing.Net.

Approche ZXing .NET :

using ZXing;
using ZXing.Windows.Compatibility;
using PdfiumViewer;
using System.Drawing;
using System.Drawing.Imaging;

public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
    var collected = new List<string>();

    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.PDF_417
    };

    using var document = PdfDocument.Load(pdfPath);
    for (int page = 0; page < document.PageCount; page++)
    {
        string temp = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png");
        try
        {
            using var rendered = document.Render(page, 200, 200, PdfRenderFlags.CorrectFromDpi);
            rendered.Save(temp, ImageFormat.Png);

            using var bmp = new Bitmap(temp);
            var decoded = reader.DecodeMultiple(bmp);
            if (decoded != null)
                collected.AddRange(decoded.Select(d => d.Text));
        }
        finally
        {
            if (File.Exists(temp))
                File.Delete(temp);
        }
    }

    return collected;
}
using ZXing;
using ZXing.Windows.Compatibility;
using PdfiumViewer;
using System.Drawing;
using System.Drawing.Imaging;

public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
    var collected = new List<string>();

    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.PDF_417
    };

    using var document = PdfDocument.Load(pdfPath);
    for (int page = 0; page < document.PageCount; page++)
    {
        string temp = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png");
        try
        {
            using var rendered = document.Render(page, 200, 200, PdfRenderFlags.CorrectFromDpi);
            rendered.Save(temp, ImageFormat.Png);

            using var bmp = new Bitmap(temp);
            var decoded = reader.DecodeMultiple(bmp);
            if (decoded != null)
                collected.AddRange(decoded.Select(d => d.Text));
        }
        finally
        {
            if (File.Exists(temp))
                File.Delete(temp);
        }
    }

    return collected;
}
Imports ZXing
Imports ZXing.Windows.Compatibility
Imports PdfiumViewer
Imports System.Drawing
Imports System.Drawing.Imaging

Public Function ExtractBarcodesFromPdf(pdfPath As String) As List(Of String)
    Dim collected As New List(Of String)()

    Dim reader As New BarcodeReader()
    reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.PDF_417
    }

    Using document = PdfDocument.Load(pdfPath)
        For page As Integer = 0 To document.PageCount - 1
            Dim temp As String = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png")
            Try
                Using rendered = document.Render(page, 200, 200, PdfRenderFlags.CorrectFromDpi)
                    rendered.Save(temp, ImageFormat.Png)

                    Using bmp As New Bitmap(temp)
                        Dim decoded = reader.DecodeMultiple(bmp)
                        If decoded IsNot Nothing Then
                            collected.AddRange(decoded.Select(Function(d) d.Text))
                        End If
                    End Using
                End Using
            Finally
                If File.Exists(temp) Then
                    File.Delete(temp)
                End If
            End Try
        Next
    End Using

    Return collected
End Function
$vbLabelText   $csharpLabel

Approche IronBarcode :

using IronBarCode;

public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
    return BarcodeReader.Read(pdfPath)
        .Select(r => r.Value)
        .ToList();
}
using IronBarCode;

public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
    return BarcodeReader.Read(pdfPath)
        .Select(r => r.Value)
        .ToList();
}
Imports IronBarCode

Public Function ExtractBarcodesFromPdf(pdfPath As String) As List(Of String)
    Return BarcodeReader.Read(pdfPath) _
        .Select(Function(r) r.Value) _
        .ToList()
End Function
$vbLabelText   $csharpLabel

La dépendance à PdfiumViewer, la boucle de rendu de la page, la configuration DPI, la création de fichiers temporaires et le bloc de nettoyage sont tous supprimés. Code-barres IronBarcode lit nativement les codes-barres des fichiers PDF et traite automatiquement toutes les pages.

Générer un code-barres

Le générateur ZXing.Net renvoie un Bitmap que les appelants doivent enregistrer en utilisant System.Drawing.Imaging. Code-barres IronBarcode renvoie un GeneratedBarcode avec des méthodes de sortie intégrées.

Approche ZXing .NET :

using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using System.Drawing;
using System.Drawing.Imaging;

public void WriteCode128(string content, string outputPath)
{
    var writer = new BarcodeWriter
    {
        Format = BarcodeFormat.CODE_128,
        Options = new EncodingOptions
        {
            Width = 400,
            Height = 120,
            Margin = 10
        }
    };

    using var bitmap = writer.Write(content);
    bitmap.Save(outputPath, ImageFormat.Png);
}
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using System.Drawing;
using System.Drawing.Imaging;

public void WriteCode128(string content, string outputPath)
{
    var writer = new BarcodeWriter
    {
        Format = BarcodeFormat.CODE_128,
        Options = new EncodingOptions
        {
            Width = 400,
            Height = 120,
            Margin = 10
        }
    };

    using var bitmap = writer.Write(content);
    bitmap.Save(outputPath, ImageFormat.Png);
}
Imports ZXing
Imports ZXing.Common
Imports ZXing.Windows.Compatibility
Imports System.Drawing
Imports System.Drawing.Imaging

Public Sub WriteCode128(content As String, outputPath As String)
    Dim writer = New BarcodeWriter With {
        .Format = BarcodeFormat.CODE_128,
        .Options = New EncodingOptions With {
            .Width = 400,
            .Height = 120,
            .Margin = 10
        }
    }

    Using bitmap = writer.Write(content)
        bitmap.Save(outputPath, ImageFormat.Png)
    End Using
End Sub
$vbLabelText   $csharpLabel

Approche IronBarcode :

using IronBarCode;

public void WriteCode128(string content, string outputPath)
{
    BarcodeWriter.CreateBarcode(content, BarcodeEncoding.Code128)
        .ResizeTo(400, 120)
        .SaveAsPng(outputPath);
}
using IronBarCode;

public void WriteCode128(string content, string outputPath)
{
    BarcodeWriter.CreateBarcode(content, BarcodeEncoding.Code128)
        .ResizeTo(400, 120)
        .SaveAsPng(outputPath);
}
Imports IronBarCode

Public Sub WriteCode128(content As String, outputPath As String)
    BarcodeWriter.CreateBarcode(content, BarcodeEncoding.Code128) _
        .ResizeTo(400, 120) _
        .SaveAsPng(outputPath)
End Sub
$vbLabelText   $csharpLabel

Si une sortie binaire est nécessaire au lieu de l'enregistrement dans un fichier, ToPngBinaryData() et ToJpegBinaryData() sont disponibles sur l'objet GeneratedBarcode renvoyé, sans aucune plomberie MemoryStream.

Référence de mappage de l'API ZXing .NET vers IronBarcode

ZXing.Net Code-barres IronBarcode Notes
new BarcodeReader() Statique — aucune instance BarcodeReader.Read(...) est un appel statique
reader.Options.PossibleFormats = nouvelle liste<BarcodeFormat> { ... } Pas nécessaire La détection automatique couvre plus de 50 formats
reader.Options.TryHarder = true Speed = ReadingSpeed.Balanced Ajustement de la précision via BarcodeReaderOptions
reader.Decode(bitmap) BarcodeReader.Read(imagePath).FirstOrDefault() Passer le chemin du fichier — aucune construction Bitmap n'est nécessaire
reader.DecodeMultiple(bitmap) BarcodeReader.Read(imagePath) Renvoie toujours une collection ; never null
result.Text result.Value Propriété renommée
result.BarcodeFormat result.Format Propriété renommée
BarcodeFormat.QR_CODE BarcodeEncoding.QRCode Changement de convention d'appellation des énumérations
BarcodeFormat.CODE_128 BarcodeEncoding.Code128 Changement de convention d'appellation des énumérations
BarcodeFormat.EAN_13 BarcodeEncoding.EAN13 Changement de convention d'appellation des énumérations
BarcodeFormat.DATA_MATRIX BarcodeEncoding.DataMatrix Changement de convention d'appellation des énumérations
BarcodeFormat.PDF_417 BarcodeEncoding.PDF417 Changement de convention d'appellation des énumérations
new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... } } BarcodeWriter.CreateBarcode(data, encoding) Usine statique, aucun objet d'options
writer.Write(data) renvoie Bitmap .SaveAsPng(path) / .ToPngBinaryData() Sortie intégrée sur GeneratedBarcode
EncodingOptions { Width, Height } .ResizeTo(width, height) Méthode de dimensionnement fluide
Prise en charge des fichiers PDF non disponible BarcodeReader.Read("file.pdf") Prise en charge native du format PDF, toutes les pages

Problèmes de migration courants et solutions

Problème 1 : Modèles d'instanciation de BarcodeReader

ZXing.Net : Les appelants créent un new BarcodeReader(), définissent reader.Options.PossibleFormats, chargent un Bitmap, appellent reader.Decode(bitmap) ou reader.DecodeMultiple(bitmap), et lisent result.Text.

Solution : Supprimez complètement l'instanciation. Remplacez le modèle complet par un appel statique :

// Before: reader creation + format config + bitmap + decode + result.Text
// After:
var result = BarcodeReader.Read(imagePath).FirstOrDefault();
var value = result?.Value ?? string.Empty;
// Before: reader creation + format config + bitmap + decode + result.Text
// After:
var result = BarcodeReader.Read(imagePath).FirstOrDefault();
var value = result?.Value ?? string.Empty;
' Before: reader creation + format config + bitmap + decode + result.Text
' After:
Dim result = BarcodeReader.Read(imagePath).FirstOrDefault()
Dim value = If(result?.Value, String.Empty)
$vbLabelText   $csharpLabel

Recherchez la base de code pour new BarcodeReader() pour trouver chaque instance. Chaque élément est supprimé, non remanié.

Problème 2 : Suppression du bloc PossibleFormats

ZXing .NET: Chaque appel de décodage est précédé d'un reader.Options.PossibleFormats = nouvelle liste<BarcodeFormat> { ... }affectation. Ces listes sont souvent longues et spécifiques à chaque projet.

Solution : Supprimez chaque bloc d'affectation PossibleFormats dans son intégralité. Code-barres IronBarcode effectue une détection automatique du format ; Aucune liste de format n'est acceptée ni requise. Si le drapeau TryHarder = true était défini en même temps que la liste des formats, remplacez-le par Speed = ReadingSpeed.Balanced sur un objet BarcodeReaderOptions si un ajustement de précision est nécessaire.

Problème 3 : Nettoyage du package de liaison

ZXing.Net : Les projets utilisant ZXing.Net.Bindings.Windows.Compatibility ont du code référencé System.Drawing.Bitmap comme type d'entrée. Les projets utilisant ZXing.Net.Bindings.ImageSharp font référence à SixLabors.ImageSharp.Image<Rgba32>. Les deux modèles cessent de fonctionner après la suppression des paquets de liaison.

Solution : Supprimez les deux packages de liaison et remplacez tout le code de chargement d'images. L'BarcodeReader.Read d'IronBarcode accepte une chaîne de chemin de fichier, un byte[], un Stream, ou un Uri — aucune construction Bitmap ou Image<t> n'est nécessaire. Les imports using System.Drawing; restants qui existaient uniquement pour le chargement Bitmap peuvent également être supprimés.

Problème 4 : conversion de result.Text en result.Value

ZXing.Net : La valeur du code-barres décodée est accessible via result.Text. Le format du code-barres est accessible via result.BarcodeFormat.

Solution : Remplacez result.Text par result.Value et result.BarcodeFormat par result.Format dans toute la base de code. Les deux changements sont des renommages de propriétés simples sans différence de comportement.

Liste de contrôle de migration ZXing .NET

Tâches préalables à la migration

Avant d'apporter des modifications, vérifiez le code source afin de trouver toutes les références à ZXing .NET :

grep -r "using ZXing" --include="*.cs" .
grep -r "new BarcodeReader" --include="*.cs" .
grep -r "PossibleFormats" --include="*.cs" .
grep -r "BarcodeFormat\." --include="*.cs" .
grep -r "reader\.Decode\|reader\.DecodeMultiple" --include="*.cs" .
grep -r "result\.Text\|result\.BarcodeFormat" --include="*.cs" .
grep -r "new BarcodeWriter\|writer\.Write\|EncodingOptions" --include="*.cs" .
grep -r "PdfiumViewer\|PdfDocument\.Load" --include="*.cs" .
grep -r "using System\.Drawing" --include="*.cs" .
grep -r "using ZXing" --include="*.cs" .
grep -r "new BarcodeReader" --include="*.cs" .
grep -r "PossibleFormats" --include="*.cs" .
grep -r "BarcodeFormat\." --include="*.cs" .
grep -r "reader\.Decode\|reader\.DecodeMultiple" --include="*.cs" .
grep -r "result\.Text\|result\.BarcodeFormat" --include="*.cs" .
grep -r "new BarcodeWriter\|writer\.Write\|EncodingOptions" --include="*.cs" .
grep -r "PdfiumViewer\|PdfDocument\.Load" --include="*.cs" .
grep -r "using System\.Drawing" --include="*.cs" .
SHELL

Documentez quels fichiers font référence aux packages de liaison ZXing (Windows vs ImageSharp) et notez où System.Drawing.Bitmap est utilisé uniquement pour l'entrée ZXing. Vérifiez le Dockerfile (si présent) pour l'installation de libgdiplus.

Tâches de mise à jour du code

  1. Supprimez les packages NuGet ZXing.Net, ZXing.Net.Bindings.Windows.Compatibility, ZXing.Net.Bindings.ImageSharp, et PdfiumViewer
  2. Installez le package NuGet IronBarcode
  3. Ajoutez IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"; au démarrage de l'application
  4. Remplacez toutes les importations using ZXing* et using SixLabors.ImageSharp* par using IronBarCode;
  5. Supprimez chaque instanciation new BarcodeReader()
  6. Supprimez chaque bloc reader.Options.PossibleFormats = ...
  7. Remplacez reader.Decode(bitmap) par BarcodeReader.Read(imagePath).FirstOrDefault()
  8. Remplacez reader.DecodeMultiple(bitmap) par BarcodeReader.Read(imagePath)
  9. Remplacez result.Text par result.Value
  10. Remplacez result.BarcodeFormat par result.Format
  11. Mettez à jour les références d'énumération BarcodeFormat.X par les équivalents BarcodeEncoding.X
  12. Remplacez new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... } }with BarcodeWriter.CreateBarcode(data, encoding).ResizeTo(w, h)
  13. Remplacez writer.Write(data) + bitmap.Save(...) par .SaveAsPng(path) ou .ToPngBinaryData()
  14. Supprimez toutes les importations using System.Drawing; qui existaient uniquement pour le chargement des bitmaps ZXing.Net
  15. Supprimez la boucle de rendu de page PdfiumViewer partout où elle était implémentée comme solution de contournement pour les PDF.
  16. Supprimez libgdiplus du Dockerfile si elle a été ajoutée pour supporter System.Drawing sur Linux

Test de post-migration

  • Vérifiez que tous les formats de codes-barres que l'application était précédemment configurée pour détecter sont bien reconnus.
  • Testez avec des images contenant des formats de codes-barres qui étaient auparavant exclus de la liste PossibleFormats, pour confirmer que la détection automatique les repère
  • Exécutez les chemins de traitement concurrents sous charge et vérifiez l'absence de conditions de concurrence ou de résultats nuls.
  • Si l'application a traité les PDF via PdfiumViewer, veuillez fournir les mêmes fichiers PDF et vérifier que les valeurs des codes-barres correspondent.
  • Vérifiez que les codes-barres générés (Code 128, code QR, etc.) présentent le format et les dimensions corrects.
  • Sur les déploiements Linux ou Docker, confirmez que la lecture d'image et la lecture PDF fonctionnent sans libgdiplus
  • Exécutez la Suite de tests complète et comparez les résultats à la référence avant migration.

Principaux avantages de la migration vers IronBarcode

Suppression des contraintes liées à la sécurité des threads : l'API statique d'IronBarcode supprime entièrement le modèle d'instance par thread. Il n'y a pas de lecteur à instancier, pas de liste de formats à configurer par thread, et pas de pool ThreadLocal à gérer. Le même appel est correct aussi bien dans les environnements monothread que dans les environnements hautement concurrents, et la correction de la concurrence est assurée par la bibliothèque plutôt que déléguée à chaque appelant.

Détection automatique du format : La suppression de la liste PossibleFormats élimine la catégorie des échecs silencieux lorsque les documents contiennent des formats de codes-barres qui n'ont pas été anticipés lors du développement. Les applications qui traitent des documents provenant de partenaires externes ou qui fonctionnent avec des normes de codes-barres en constante évolution n'ont plus besoin de maintenir une liste de formats pour rester fiables.

Traitement PDF natif : La boucle de rendu de PdfiumViewer — son énumération des pages, sa configuration DPI, le cycle de vie des fichiers temporaires et son code de nettoyage — est entièrement supprimée. Les applications qui nécessitaient auparavant deux bibliothèques (ZXing .NET et un moteur de rendu PDF) pour traiter un code-barres PDF n'en utilisent désormais qu'une seule. La réduction des dépendances déployées simplifie à la fois la compilation et la surface de déploiement.

Package unique multiplateforme : la distinction entre les packages de liaison pour les déploiements Windows et Linux est éliminée. Le même appel BarcodeReader.Read(path) se compile et se comporte de manière identique sur toutes les plateformes cibles, éliminant le besoin de conditionnels de plateforme dans le code de chargement d'images et simplifiant les flux de travail de développement multiplateformes et de containerisation.

Code d'infrastructure réduit : Le résultat le plus significatif de la migration est la suppression de l'infrastructure environnante — les blocs de chargement Bitmap, les listes de format, les boucles de rendu PdfiumViewer, les pools ThreadLocal — qui existaient dans les intégrations ZXing .NET non pas pour effectuer le traitement des codes-barres, mais pour satisfaire aux exigences architecturales de la bibliothèque. Ce qui subsiste après la migration, c'est la logique des codes-barres elle-même. Pour un contexte plus complet sur les taux de détection et les scénarios de numérisation, la comparaison entre les scanners ZXing .NET et IronBarcode offre une analyse plus large.

Veuillez noterGhostscript, PDFium, ZXing.NET, et iText sont des marques déposées de leurs propriétaires respectifs. Ce site n'est pas affilié, approuvé ou sponsorisé par Artifex Software, Chromium Project, Google, ZXing.NET, ou iText Group. Tous les noms de produits, logos, et marques sont la propriété de leurs propriétaires respectifs. Les comparaisons sont à titre informatif uniquement et reflètent les informations publiquement disponibles au moment de l'écriture.

Questions Fréquemment Posées

Pourquoi devrais-je migrer de ZXing.Net vers IronBarcode ?

Les raisons les plus courantes sont la simplification des licences (suppression de la complexité du SDK + de la clé d'exécution), l'élimination des limites de débit, la prise en charge native des PDF, l'amélioration du déploiement Docker/CI/CD et la réduction de l'API boilerplate dans le code de production.

Comment remplacer les appels API de ZXing.Net par IronBarcode ?

Remplacer la création d'instance et le modèle de licence par IronBarCode.License.LicenseKey = "key". Remplacer les appels au lecteur par BarcodeReader.Read(path) et les appels à l'écrivain par BarcodeWriter.CreateBarcode(data, encoding). Les méthodes statiques ne nécessitent aucune gestion d'instance.

Quelle quantité de code change lors de la migration de ZXing.Net vers IronBarcode ?

La plupart des migrations permettent de réduire le nombre de lignes de code. Les modèles de licence, les constructeurs d'instances et la configuration explicite des formats sont supprimés. Les principales opérations de lecture/écriture sont converties en équivalents plus courts d'IronBarcode avec des objets de résultat plus propres.

Dois-je conserver à la fois ZXing.Net et IronBarcode installés pendant la migration ?

Non. La plupart des migrations sont des remplacements directs plutôt que des opérations parallèles. Migrez une classe de service à la fois, remplacez la référence NuGet et mettez à jour les modèles d'instanciation et d'appel d'API avant de passer à la classe suivante.

Quel est le nom du package NuGet pour IronBarcode ?

Le paquet est "IronBarcode" (avec un B et un C majuscules). Installez-le avec "Install-Package IronBarCode" ou "dotnet add package IronBarCode". La directive using dans le code est "using IronBarCode ;".

Comment IronBarcode simplifie-t-il le déploiement de Docker par rapport à ZXing.Net ?

IronBarcode est un package NuGet sans fichiers SDK externes ni configuration de licence montée. Dans Docker, définissez la variable d'environnement IRONBARCODE_LICENSE_KEY et le paquetage gère la validation de la licence au démarrage.

IronBarcode détecte-t-il automatiquement tous les formats de codes-barres après avoir migré depuis ZXing.Net ?

Oui. IronBarcode détecte automatiquement la symbologie dans tous les formats pris en charge. L'énumération explicite des BarcodeTypes n'est pas nécessaire. Si le format est déjà connu et que la performance est importante, BarcodeReaderOptions permet de restreindre l'espace de recherche en tant qu'optimisation.

IronBarcode peut-il lire des codes-barres à partir de PDF sans bibliothèque séparée ?

Oui, BarcodeReader.Read("document.pdf") traite les fichiers PDF de manière native. Les résultats incluent le numéro de page, le format, la valeur et la confiance pour chaque code-barres trouvé. Aucune étape de rendu PDF externe n'est requise.

Comment IronBarcode gère-t-il le traitement parallèle des codes-barres ?

Les méthodes statiques d'IronBarcode sont sans état et à l'abri des threads. Utilisez Parallel.ForEach directement sur les listes de fichiers sans gestion d'instance par thread. BarcodeReaderOptions.MaxParallelThreads contrôle le budget interne des threads.

Quelles propriétés de résultat changent lors de la migration de ZXing.Net vers IronBarcode ?

Renommages courants : BarcodeValue devient Value, BarcodeType devient Format. Les résultats d'IronBarcode ajoutent également Confidence et PageNumber. Une recherche et un remplacement à l'échelle de la solution gèrent les renommages dans le code existant de traitement des résultats.

Comment configurer l'octroi de licences IronBarcode dans un pipeline CI/CD ?

Stockez IRONBARCODE_LICENSE_KEY en tant que secret de pipeline et attribuez IronBarCode.License.LicenseKey dans le code de démarrage de l'application. Un seul secret couvre tous les environnements, y compris le développement, les tests, la mise en scène et la production.

IronBarcode prend-il en charge la génération de codes QR avec un style personnalisé ?

Oui. QRCodeWriter.CreateQrCode() prend en charge les couleurs personnalisées via ChangeBarCodeColor(), l'intégration de logos via AddBrandLogo(), les niveaux de correction d'erreur configurables et plusieurs formats de sortie, notamment PNG, JPG, PDF et stream.

Curtis Chau
Rédacteur technique

Curtis Chau détient un baccalauréat en informatique (Université de Carleton) et se spécialise dans le développement front-end avec expertise en Node.js, TypeScript, JavaScript et React. Passionné par la création d'interfaces utilisateur intuitives et esthétiquement plaisantes, Curtis aime travailler avec des frameworks modernes ...

Lire la suite

Équipe de soutien Iron

Nous sommes en ligne 24 heures sur 24, 5 jours sur 7.
Chat
Email
Appelez-moi