Schreiben von Unicode und internationalen BarCodes in C# | IronPDF
Von ZXing.Net zu IronBarcode migrieren
Dieser Leitfaden beschreibt die vollständige Migration von ZXing .NET zu IronBarcode for .NET Anwendungen, die Barcodes lesen und generieren. Es behandelt die Entfernung des Kernpakets von ZXing.Net und der Bindungspakete, die Beseitigung von PdfiumViewer-Workarounds, wo vorhanden, und den Ersatz jeder zustandsbehafteten BarcodeReader Instanziierung durch die statische API von IronBarcode. Jeder Abschnitt enthält Vorher-Nachher-Codebeispiele, die den in ZXing .NET Integrationen am häufigsten vorkommenden Mustern entnommen sind.
Warum von ZXing .NET migrieren?
ZXing .NET hat der .NET Community über ein Jahrzehnt lang als kostenlose Apache 2.0 Barcode-Bibliothek gute Dienste geleistet. Allerdings werden einige architektonische Beschränkungen mit zunehmendem Umfang oder steigender Komplexität der Anwendungen zu Betriebskosten.
Thread-Sicherheitsbesitz: ZXing.Net's BarcodeReader ist ein zustandsbehaftetes Objekt. In der Dokumentation der Bibliothek selbst heißt es, dass Instanzen nicht threadübergreifend geteilt werden dürfen. In der Praxis bedeutet dies, dass jeder parallele Verarbeitungspfad – jede Controller-Aktion, die gleichzeitig Anfragen bearbeitet, jede Aufgabe in einem parallelen Batch – seinen eigenen Reader zuweisen, konfigurieren und verwerfen muss. Mit zunehmendem Anfragevolumen führt dieses Zuweisungsmuster zu messbarem Speicherdruck. Die ThreadLocal<BarcodeReader>-Alternative reduziert die Zuweisungshäufigkeit, bringt jedoch ihre eigene Entsorgungskomplexität mit sich. In beiden Fällen ist die Korrektheit unter Parallelität das Problem des Aufrufers und keine Garantie der Bibliothek.
Formatspezifikationsrisiko: ZXing.Net erfordert, dass reader.Options.PossibleFormats vor jeder Decodierung ausgefüllt ist. Ein Barcode in einem Format, das nicht in dieser Liste vorhanden ist, gibt null zurück — keine Ausnahme, keine Warnung, keine Angabe, dass ein Barcode vorhanden war, aber nicht erkannt wurde. Für Anwendungen, die Dokumente von externen Partnern erhalten, ist dieses Stille-Verpassungsverhalten ein Zuverlässigkeitsrisiko: eine falsch gelieferte Bestellung, ein verpasstes Patienteneincheckdatensatz oder ein Audit-Eintrag, der nie geschrieben wird, können alle aus einer Formatliste stammen, die für ein früheres Erfordernis konfiguriert und nie aktualisiert wurde.
PDF-Verarbeitungslücke: ZXing .NET liest nur Bitmaps. Wenn es sich bei den Quelldokumenten um PDFs handelt – Rechnungen, Versandmanifeste, Konformitätszertifikate – müssen die Aufrufer eine separate PDF-Rendering-Bibliothek integrieren (PdfiumViewer ist die gebräuchlichste), eine Seitenaufzählungsschleife implementieren, DPI konfigurieren, temporäre Dateien verwalten und die Bereinigung sowohl im Erfolgs- als auch im Fehlerfall durchführen. Dies sind 30 bis 50 Zeilen Infrastrukturcode pro Integration, die ausschließlich dazu dienen, das, was ZXing .NET nicht lesen kann (PDFs), in das umzuwandeln, was es lesen kann (Bitmaps). Diese Infrastruktur hat ihre eigenen Abhängigkeiten, ihre eigenen Bereitstellungsanforderungen und ihre eigenen Fehlermodi.
Plattform-Bindungsfragmentierung: Die Bildladefunktion von ZXing.Net ist auf plattformspezifische Bindungspakete aufgeteilt. Die Windows-Bindung verwendet System.Drawing.Bitmap; die plattformübergreifende Bindung verwendet SixLabors.ImageSharp mit einem anderen generischen Typparameter und einer anderen using-Direktive. Ein Projekt, das auf Windows beginnt und später auf Linux containerisiert wird, muss sowohl seine NuGet-Verweise als auch seinen Bildlade-Code ändern. Zwei Codepfade für dieselbe Operation erhöhen die Angriffsfläche für Fehler und erschweren zukünftige Änderungen in der Scanschicht.
Das grundsätzliche Problem
Die deutlichste Veranschaulichung der ZXing .NET -Architektur ist der Unterschied zwischen einem Single-Thread-Aufruf und einem Concurrent-Aufruf. In ZXing .NET erfordert die parallele Verarbeitung die Erstellung eines vollständigen Reader-Objekts pro paralleler Operation:
// 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)
IronBarcode entfernt das Objekt vollständig. Der statische Aufruf ist derselbe, egal ob er auf einem oder hundert Threads ausgeführt wird:
// 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)
IronBarcode vs. ZXing .NET: Funktionsvergleich
| Feature | ZXing.Net | IronBarcode |
|---|---|---|
| Lizenz | Apache 2.0 (kostenlos) | Kommerziell |
| Thread-Sicherheit | Nicht threadsicher – für jeden Thread ist eine neue Instanz erforderlich. | Threadsichere statische API |
| Formaterkennung | Manuell — PossibleFormats Liste erforderlich |
Automatisch – über 50 Formate |
| PDF-Lesen | Nein – benötigt PdfiumViewer oder ein ähnliches Programm. | Native — einzelner Methodenaufruf |
| Windows, Linux, macOS, Docker, Azure, AWS. | Separate Bindungspakete pro Plattform | Einzelpaket, alle Plattformen |
| Mehrere Barcodes pro Bild | Ja — DecodeMultiple |
Ja — Standartverhalten |
| Barcode-Generierung | Gibt Bitmap zurück, erfordert manuelles Speichern |
Fluent API mit integrierter Ausgabe |
| Unterstützung für QR-Code-Logos | Nein | Ja |
| QR-Code-Farbsteuerung | Nein | Ja |
| Wiederherstellung beschädigter Barcodes | TryHarder Flag |
ML-gestützte Bildkorrektur |
| Zusätzliche Docker-Abhängigkeiten | Kann libgdiplus erfordern |
None |
| Unterstützung für kommerzielle SLAs | Nein | Ja |
| Erforderliche NuGet -Pakete | 2–3 (Kern + Bindung + optionales ImageSharp) | 1 |
Schnellstart
Schritt 1: Entfernen Sie die ZXing .NET -Pakete
Entfernen Sie alle ZXing .NET und zugehörigen Pakete aus dem Projekt:
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
Wenn die nativen PdfiumViewer-Binärdateien als separates Paket installiert wurden:
dotnet remove package PdfiumViewer.Native.x64.v8-xfa
dotnet remove package PdfiumViewer.Native.x64.v8-xfa
Wenn die Dockerdatei apt-get install -y libgdiplus enthält — hinzugefügt, um System.Drawing über die Windows-Bindung auf Linux zu unterstützen — kann diese Zeile nach der Migration entfernt werden.
Schritt 2: IronBarcode installieren
dotnet add package IronBarcode
dotnet add package IronBarcode
Es werden keine zusätzlichen Bindungspakete oder plattformspezifische Abhängigkeiten benötigt. Das gleiche NuGet Paket läuft unter Windows, Linux, macOS und in Docker-Containern. Für Details zur Bereitstellung ist die Einrichtungsanleitung für IronBarcode Docker und Linux mit dem genauen Dockerfile-Muster versehen.
Schritt 3: Namensräume aktualisieren und Lizenz initialisieren
Entfernen Sie alle ZXing-bezogenen Namensräume aus jeder Datei, die Barcode-Operationen verwendet:
// 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
Fügen Sie die Lizenzinitialisierung beim Anwendungsstart vor allen Barcode-Operationen hinzu:
// 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"
Der Lizenzschlüssel ist eine einfache Zeichenfolge, die aus einer Umgebungsvariable, appsettings.json oder einem Geheimnismanager geladen werden kann. Es gibt keine Datei zu finden und keinen Pfad zu konfigurieren.
Beispiele für die Code-Migration
Lesen eines einzelnen Barcodes aus einem Bild
Dieses Beispiel ersetzt das gängigste ZXing .NET Nutzungsmuster: Instanziieren eines Readers, Konfigurieren der Formatliste, Laden einer Bitmap und Dekodieren.
ZXing .NET -Ansatz:
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
IronBarcode -Ansatz:
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
Die Formatliste, die Bitmap Zuweisung und der using-Block werden alle entfernt. IronBarcode akzeptiert einen Dateipfad direkt und erkennt alle unterstützten Formate automatisch. Die Eigenschaft, die zuvor die decodierte Zeichenfolge zurückgab, war result.Text in ZXing.Net; sie ist result.Value in IronBarcode.
Alle Barcodes aus einem Bild lesen
Dieses Beispiel ersetzt DecodeMultiple, das in ZXing.Net eine umfassende Formatliste erfordert, um stille Fehlschläge zu vermeiden.
ZXing .NET -Ansatz:
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
IronBarcode -Ansatz:
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
BarcodeReader.Read gibt immer eine Sammlung zurück und gibt niemals null zurück, wodurch der Null-Wächter für das Ergebnis entfällt. Um das Gleichgewicht zwischen Genauigkeit und Geschwindigkeit zu optimieren, siehe den Leitfaden zu den Lesegeschwindigkeitsoptionen, der das ReadingSpeed enum behandelt, ohne den Formatscope einzuengen.
Gleichzeitige Stapelverarbeitung
Dieses Beispiel verdeutlicht den Unterschied in der Gewindesicherheit am deutlichsten. ZXing .NET benötigt für jeden parallelen Vorgang einen neuen Reader; IronBarcode verwendet unabhängig vom Parallelitätsgrad denselben statischen Aufruf.
ZXing .NET -Ansatz:
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
IronBarcode -Ansatz:
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
Es gibt keine Leserinstanz, die geschützt oder isoliert werden müsste. Informationen zu asynchronen Pipeline-Mustern und zur Konfiguration der Thread-Anzahl finden Sie im Leitfaden zum asynchronen und multithreadbasierten Lesen von Barcodes .
Barcodes aus einer PDF-Datei extrahieren
Dieses Beispiel ersetzt die PdfiumViewer-Render-Schleife. Wenn die bestehende Integration statt PdfiumViewer Ghostscript oder iText verwendet hat, sieht der Vorblock im Detail anders aus, ist aber strukturell identisch: eine Seitendurchlauf-Schleife, die Bitmaps an ZXing.Net übergibt.
ZXing .NET -Ansatz:
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
IronBarcode -Ansatz:
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
Die PdfiumViewer-Abhängigkeit, die Seitenrenderschleife, die DPI-Konfiguration, die Erstellung der temporären Datei und der Aufräumblock werden alle entfernt. IronBarcode liest Barcodes nativ aus PDFs und verarbeitet alle Seiten automatisch.
Barcode generieren
Der ZXing.Net-Schreiber gibt ein Bitmap zurück, das Anrufer mit System.Drawing.Imaging speichern müssen. IronBarcode gibt ein GeneratedBarcode mit integrierten Ausgabemethoden zurück.
ZXing .NET -Ansatz:
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
IronBarcode -Ansatz:
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
Wenn eine binäre Ausgabe anstelle des Speicherns in einer Datei benötigt wird, sind ToPngBinaryData() und ToJpegBinaryData() auf dem zurückgegebenen GeneratedBarcode Objekt ohne jegliche MemoryStream-Verrohrung verfügbar.
ZXing .NET API zu IronBarcode Mapping-Referenz
| ZXing.Net | IronBarcode | Notizen |
|---|---|---|
new BarcodeReader() |
Statisch – keine Instanz | BarcodeReader.Read(...) ist ein statischer Aufruf |
reader.Options.PossibleFormats = new List<BarcodeFormat> { ... } |
Nicht erforderlich | Die automatische Erkennung deckt alle über 50 Formate ab. |
reader.Options.TryHarder = true |
Speed = ReadingSpeed.Balanced |
Genauigkeitsabstimmung über BarcodeReaderOptions |
reader.Decode(bitmap) |
BarcodeReader.Read(imagePath).FirstOrDefault() |
Dateipfad übergeben — keine Bitmap Konstruktion erforderlich |
reader.DecodeMultiple(bitmap) |
BarcodeReader.Read(imagePath) |
Gibt immer eine Sammlung zurück; never null |
result.Text |
result.Value |
Immobilie umbenannt |
result.BarcodeFormat |
result.Format |
Immobilie umbenannt |
BarcodeFormat.QR_CODE |
BarcodeEncoding.QRCode |
Änderung der Namenskonvention für Enumerationen |
BarcodeFormat.CODE_128 |
BarcodeEncoding.Code128 |
Änderung der Namenskonvention für Enumerationen |
BarcodeFormat.EAN_13 |
BarcodeEncoding.EAN13 |
Änderung der Namenskonvention für Enumerationen |
BarcodeFormat.DATA_MATRIX |
BarcodeEncoding.DataMatrix |
Änderung der Namenskonvention für Enumerationen |
BarcodeFormat.PDF_417 |
BarcodeEncoding.PDF417 |
Änderung der Namenskonvention für Enumerationen |
new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... } } |
BarcodeWriter.CreateBarcode(data, encoding) |
Statische Fabrik, kein Optionsobjekt |
writer.Write(data) gibt Bitmap zurück |
.SaveAsPng(path) / .ToPngBinaryData() |
Integrierte Ausgabe auf GeneratedBarcode |
EncodingOptions { Width, Height } |
.ResizeTo(width, height) |
Fluent-Dimensionierungsmethode |
| Keine PDF-Unterstützung | BarcodeReader.Read("file.pdf") |
Native PDF-Unterstützung, alle Seiten |
Gängige Migrationsprobleme und Lösungen
Ausgabe 1: Instanziierungsmuster für Barcode-Lesegeräte
ZXing.Net: Anrufer erstellen eine new BarcodeReader(), setzen reader.Options.PossibleFormats, laden eine Bitmap, rufen reader.Decode(bitmap) oder reader.DecodeMultiple(bitmap) auf und lesen result.Text.
Lösung: Die Instanziierung vollständig entfernen. Ersetzen Sie das vollständige Muster durch einen statischen Aufruf:
// 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)
Durchsuchen Sie die Codebasis nach new BarcodeReader(), um jede Instanz zu finden. Jeder einzelne Eintrag wird entfernt, nicht refaktoriert.
Problem 2: Entfernung des PossibleFormats-Blocks
ZXing .NET: Jedem Dekodieraufruf geht ein reader.Options.PossibleFormats = new List voraus.<BarcodeFormat> { ... }Zuweisung. Diese Listen sind oft lang und projektspezifisch.
Lösung: Löschen Sie jedes PossibleFormats Zuweisungsblock vollständig. IronBarcode führt eine automatische Formaterkennung durch; Es wird keine Formatliste akzeptiert oder benötigt. Wenn das TryHarder = true-Flag zusammen mit der Formatliste gesetzt wurde, ersetzen Sie es durch Speed = ReadingSpeed.Balanced auf einem BarcodeReaderOptions Objekt, wenn eine Genauigkeitsabstimmung erforderlich ist.
Problem 3: Bereinigung des Bindungspakets
ZXing.Net: Projekte, die ZXing.Net.Bindings.Windows.Compatibility verwenden, haben Code, der sich auf System.Drawing.Bitmap als Eingabetyp bezieht. Projekte, die ZXing.Net.Bindings.ImageSharp verwenden, beziehen sich auf SixLabors.ImageSharp.Image<Rgba32>. Beide Muster funktionieren nicht mehr, nachdem die Bindungspakete entfernt wurden.
Lösung: Entfernen Sie beide Binding-Pakete und ersetzen Sie den gesamten Code zum Laden von Bildern. IronBarcode's BarcodeReader.Read akzeptiert einen Dateipfad als Zeichenfolge, eine byte[], eine Stream oder eine Uri — keine Bitmap oder Image<t> Konstruktion ist erforderlich. Übrige using System.Drawing; Importe, die ausschließlich zum Bitmap Laden existierten, können ebenfalls entfernt werden.
Problem 4: result.Text zu result.Value
ZXing.Net: Der decodierte Barcode-Wert wird über result.Text aufgerufen. Das Barcode-Format wird über result.BarcodeFormat aufgerufen.
Lösung: Ersetzen Sie result.Text durch result.Value und result.BarcodeFormat durch result.Format in der gesamten Codebasis. Beide Änderungen sind einfache Eigenschafts-Umbenennungen ohne Verhaltensunterschied.
ZXing .NET Migrations-Checkliste
Vor der Migration anfallende Aufgaben
Prüfen Sie den Quellcode auf alle ZXing .NET -Referenzen, bevor Sie Änderungen vornehmen:
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" .
Dokumentieren Sie, welche Dateien auf ZXing-Bindungspakete (Windows vs. ImageSharp) verweisen und vermerken Sie, wo System.Drawing.Bitmap ausschließlich für ZXing-Eingaben verwendet wird. Überprüfen Sie die Dockerdatei (falls vorhanden) auf libgdiplus Installation.
Aufgaben der Code-Aktualisierung
- Entfernen Sie
ZXing.Net,ZXing.Net.Bindings.Windows.Compatibility,ZXing.Net.Bindings.ImageSharpundPdfiumViewerNuGet-Pakete - Installieren Sie das
IronBarcodeNuGet-Paket - Fügen Sie
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";zum Anwendungsstart hinzu - Ersetzen Sie alle
using ZXing*undusing SixLabors.ImageSharp*Importe durchusing IronBarCode; - Entfernen Sie jede
new BarcodeReader()Instanziierung - Löschen Sie jeden
reader.Options.PossibleFormats = ...Block - Ersetzen Sie
reader.Decode(bitmap)durchBarcodeReader.Read(imagePath).FirstOrDefault() - Ersetzen Sie
reader.DecodeMultiple(bitmap)durchBarcodeReader.Read(imagePath) - Ersetzen Sie
result.Textdurchresult.Value - Ersetzen Sie
result.BarcodeFormatdurchresult.Format - Aktualisieren Sie
BarcodeFormat.XEnum-Referenzen zuBarcodeEncoding.XÄquivalenten - Ersetzen Sie
new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... } }withBarcodeWriter.CreateBarcode(data, encoding).ResizeTo(w, h) - Ersetzen Sie
writer.Write(data)+bitmap.Save(...)durch.SaveAsPng(path)oder.ToPngBinaryData() - Entfernen Sie alle
using System.Drawing;Importe, die ausschließlich für ZXing.Net Bitmap-Laden existierten - Entfernen Sie die PDFViewer-Seitenrenderschleife überall dort, wo sie als PDF-Workaround implementiert wurde.
- Entfernen Sie
libgdiplusaus der Dockerdatei, wenn es hinzugefügt wurde, umSystem.Drawingauf Linux zu unterstützen
Post-Migrationstests
- Überprüfen Sie, ob jedes Barcode-Format, für dessen Erkennung die Anwendung zuvor konfiguriert wurde, erfolgreich erkannt wird.
- Testen Sie mit Bildern, die Barcode-Formate enthalten, die zuvor von der
PossibleFormats-Liste ausgeschlossen waren, um sicherzustellen, dass die automatische Erkennung sie erfasst. - Führen Sie die parallelen Verarbeitungspfade unter Last aus und stellen Sie sicher, dass keine Race Conditions oder Null-Ergebnisse auftreten.
- Falls die Anwendung PDFs über PdfiumViewer verarbeitet hat, geben Sie dieselben PDF-Eingaben an und überprüfen Sie, ob die Barcode-Werte übereinstimmen.
- Prüfen Sie, ob die generierten Barcodes (Code 128, QR-Code usw.) das korrekte Ausgabeformat und die korrekten Abmessungen aufweisen.
- Bestätigen Sie auf Linux- oder Docker-Bereitstellungen, dass das Lesen von Bildern und von PDFs ohne
libgdiplusfunktioniert - Führen Sie die vollständige Suite aus und vergleichen Sie die Ausgabe mit der Baseline vor der Migration.
Wichtigste Vorteile der Migration zu IronBarcode
Wegfall des Thread-Sicherheitsaufwands: Die statische API von IronBarcode beseitigt das Instanzmuster pro Thread vollständig. Es gibt keinen Leser zum Instanziieren, keine Formatliste pro Thread zu konfigurieren und keinen ThreadLocal Pool zu verwalten. Derselbe Aufruf ist sowohl in Single-Thread- als auch in hochgradig parallelen Umgebungen korrekt, und die Parallelitätskorrektheit wird von der Bibliothek gewährleistet und nicht an jeden Aufrufer delegiert.
Automatische Format-Erkennung: Das Entfernen der PossibleFormats-Liste beseitigt die Kategorie der stillen-Fehltreffer, die auftreten, wenn Dokumente Barcode-Formate enthalten, die während der Entwicklung nicht erwartet wurden. Anwendungen, die Dokumente von externen Partnern verarbeiten oder mit sich entwickelnden Barcode-Standards arbeiten, benötigen keine Formatlistenpflege mehr, um zuverlässig zu bleiben.
Native PDF-Verarbeitung: Die PdfiumViewer-Rendering-Schleife – einschließlich Seitenaufzählung, DPI-Konfiguration, Lebenszyklus temporärer Dateien und Aufräumcode – wird vollständig entfernt. Anwendungen, die bisher zwei Bibliotheken (ZXing .NET und einen PDF-Renderer) zur Verarbeitung eines PDF-Barcodes benötigten, verwenden jetzt nur noch eine. Die Reduzierung der bereitgestellten Abhängigkeiten vereinfacht sowohl den Build- als auch den Bereitstellungsprozess.
Einheitliches plattformübergreifendes Paket: Die Unterscheidung zwischen Windows- und Linux-Bereitstellungen mittels Bindungspaketen entfällt. Der gleiche BarcodeReader.Read(path)-Aufruf kompiliert und verhält sich identisch auf allen Zielplattformen, wodurch die Notwendigkeit von Plattformkonditionals im Bildlade-Code entfällt und die plattformübergreifende Entwicklung und Containerisierungs-Workflows vereinfacht werden.
Reduzierter Infrastrukturcode: Das wichtigste Ergebnis der Migration ist die Entfernung der umgebenden Infrastruktur – der Bitmap-Ladeblöcke, der Formatlisten, der PdfiumViewer-Renderschleifen, der ThreadLocal-Pools –, die in ZXing .NET -Integrationen nicht für die Barcode-Verarbeitung, sondern zur Erfüllung der architektonischen Anforderungen der Bibliothek existierten. Was nach der Migration übrig bleibt, ist die Barcode-Logik selbst. Für einen umfassenderen Kontext zu Erkennungsraten und Scan-Szenarien bietet der Scannervergleich ZXing .NET vs. IronBarcode eine detailliertere Analyse.
Häufig gestellte Fragen
Warum sollte ich von ZXing.Net zu IronBarcode migrieren?
Zu den häufigsten Gründen gehören die Vereinfachung der Lizenzierung (Beseitigung der Komplexität von SDK und Laufzeitschlüsseln), die Beseitigung von Durchsatzbeschränkungen, die Verbesserung der nativen PDF-Unterstützung, die Verbesserung der Docker/CI/CD-Bereitstellung und die Verringerung von API-Boilerplate im Produktionscode.
Wie kann ich ZXing.Net-API-Aufrufe durch IronBarcode ersetzen?
Ersetzen Sie Instanzerstellung und Lizenzierung durch IronBarCode.License.LicenseKey = "key". Ersetzen Sie die Leseaufrufe durch BarcodeReader.Read(path) und die Schreibaufrufe durch BarcodeWriter.CreateBarcode(data, encoding). Statische Methoden erfordern keine Instanzverwaltung.
Wie viel Code ändert sich bei der Migration von ZXing.Net zu IronBarcode?
Die meisten Migrationen führen zu weniger Codezeilen. Lizenzierungs-Boilerplate, Instanzkonstruktoren und explizite Formatkonfiguration werden entfernt. Zentrale Lese-/Schreibvorgänge werden auf kürzere IronBarcode-Äquivalente mit saubereren Ergebnisobjekten abgebildet.
Muss ich während der Migration sowohl ZXing.Net als auch IronBarcode installiert lassen?
Nein. Die meisten Migrationen sind direkte Ersetzungen und keine Paralleloperationen. Migrieren Sie eine Serviceklasse nach der anderen, ersetzen Sie die NuGet-Referenz und aktualisieren Sie die Instanzierungs- und API-Aufrufmuster, bevor Sie zur nächsten Klasse übergehen.
Wie lautet der NuGet-Paketname für IronBarcode?
Das Paket ist 'IronBarCode' (mit großem B und C). Installieren Sie es mit 'Install-Package IronBarCode' oder 'dotnet add package IronBarCode'. Die using-Anweisung im Code lautet 'using IronBarCode;'.
Wie vereinfacht IronBarcode die Docker-Bereitstellung im Vergleich zu ZXing.Net?
IronBarcode ist ein NuGet-Paket, für das keine externen SDK-Dateien oder Lizenzkonfigurationen erforderlich sind. In Docker setzen Sie die Umgebungsvariable IRONBARCODE_LICENSE_KEY und das Paket übernimmt die Lizenzvalidierung beim Start.
Erkennt IronBarcode for .NET nach der Migration von ZXing.Net automatisch alle Barcode-Formate?
Ja, IronBarcode erkennt automatisch die Symbologie aller unterstützten Formate. Eine explizite Aufzählung von BarcodeTypes ist nicht erforderlich. Wenn das Format bereits bekannt ist und die Leistung eine Rolle spielt, ermöglicht BarcodeReaderOptions die Einschränkung des Suchraums als eine Optimierung.
Kann IronBarcode Barcodes aus PDFs ohne eine separate Bibliothek lesen?
Ja, BarcodeReader.Read("document.pdf") verarbeitet PDF-Dateien nativ. Die Ergebnisse enthalten PageNumber, Format, Value und Confidence für jeden gefundenen Barcode. Es ist kein externer PDF-Rendering-Schritt erforderlich.
Wie handhabt IronBarcode die parallele Verarbeitung von Barcodes?
Die statischen Methoden von IronBarcode sind zustandslos und thread-sicher. Verwenden Sie Parallel.ForEach direkt über Dateilisten ohne Instanzmanagement pro Thread. BarcodeReaderOptions.MaxParallelThreads steuert das interne Thread-Budget.
Welche Ergebniseigenschaften ändern sich bei der Migration von ZXing.Net zu IronBarcode?
Übliche Umbenennungen: BarcodeValue wird zu Value, BarcodeType wird zu Format. IronBarcode-Ergebnisse fügen auch Confidence und PageNumber hinzu. Eine lösungsweite Such- und Ersetzungsfunktion übernimmt die Umbenennungen im bestehenden Ergebnisverarbeitungscode.
Wie kann ich die IronBarcode-Lizenzierung in einer CI/CD-Pipeline einrichten?
Speichern Sie IRONBARCODE_LICENSE_KEY als Pipeline-Geheimnis und weisen Sie IronBarCode.License.LicenseKey im Startup-Code der Anwendung zu. Ein Geheimnis deckt alle Umgebungen ab, einschließlich Entwicklung, Test, Staging und Produktion.
Unterstützt IronBarcode die Generierung von QR-Codes mit benutzerdefiniertem Styling?
Ja. QRCodeWriter.CreateQrCode() unterstützt benutzerdefinierte Farben über ChangeBarCodeColor(), das Einbetten von Logos über AddBrandLogo(), konfigurierbare Fehlerkorrekturstufen und mehrere Ausgabeformate einschließlich PNG, JPG, PDF und Stream.

