跳至頁尾內容
影片

如何在 C# | IronPDF 中編寫 Unicode 和國際語言條碼

從ZXing.Net遷移到IronBarcode

本指南涵蓋了從ZXing.Net遷移到IronBarcode的完整過程,適用於讀取和生成條碼的.NET應用程式。 它解決了移除ZXing.Net的核心包和綁定包的問題,消除了在使用PdfiumViewer時出現的變通辦法,以及用IronBarcode的靜態API替換每個有狀態的BarcodeReader實例。 每個部分都包括從ZXing.Net整合中最常見的範例中得出的程式碼前後比較。

為什麼從ZXing.Net遷移

ZXing.Net 作為一個免費的 Apache 2.0 條碼庫,為 .NET 社區服務了十多年。 然而,隨著應用程式規模或複雜度的增加,一些架構約束已成為運營成本。

執行緒安全擁有權: ZXing.Net 的BarcodeReader是一個有狀態的物件。 該庫的自身文件指出,不得跨執行緒共享實例。 在實踐中,這意味著每個並行處理路徑——每個控制器操作處理同時響應,每個並行批次中的任務——都必須分配、配置和丟棄其自己的讀取器。 隨著請求量的增加,這種分配模式會產生可測量的記憶體壓力。 ThreadLocal<BarcodeReader> 的替代方法減少了分配頻率,但引入了自己的銷毀複雜性。 在這兩種情況下,並行性下的正確性是呼叫者的問題,而不是由庫提供的保證。

格式規範風險: ZXing.Net 需要在每次解碼操作之前填充reader.Options.PossibleFormats。 如果條碼是該列表中不存在的格式,則返回null——沒有例外、沒有警告、沒有指示條碼存在但未被識別的提示。 對於接收來自外部合作夥伴的文件的應用程式,這種靜默錯失行為是一個可靠性風險:誤發的訂單、錯過的患者登記記錄,或審核記錄未曾寫入,這些都可能源於配置為先前需求且從未更新的格式列表。

PDF 處理缺口: ZXing.Net 僅讀取位圖。 當源文件是 PDFs——發票、運單、合規證書時——呼叫者必須整合一個單獨的 PDF 渲染庫(PdfiumViewer 是最常見的),實現頁面枚舉迴圈,配置 DPI,管理臨時文件,並在成功和失敗的路徑上進行清理。 這是一個僅為將ZXing.Net無法讀取的(PDFs)轉換成能讀取的(位圖)而存在的整合,每個整合大約需要30到50行基礎設施程式碼。 該基礎設施有其自己的依賴項、部署要求和失敗模式。

平台綁定碎片化: ZXing.Net 的圖像載入功能跨平台特定綁定包分割。 Windows 綁定使用 System.Drawing.Bitmap; 跨平台綁定使用 SixLabors.ImageSharp,具有不同的泛型型別參數和不同的 using 指令。一個在 Windows 上啟動後又在 Linux 上容器化的專案必須更改其 NuGet 參考和其圖像載入程式碼。 對同一操作的兩個程式碼路徑增加了錯誤的表面積,並增加了在掃描層進行未來更改的阻力。

基本問題

ZXing.Net 架構最清晰的說明是單一執行緒調用與並行調用之間的差距。 在 ZXing.Net 中,並行處理需要為每個並行操作建立一個完整的讀取器物件:

// 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 完全移除了該物件。 無論是在一個執行緒上運行還是在一百個執行緒上運行,靜態調用都是相同的:

// 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

IronBarcodevs ZXing.Net:功能比較

功能 ZXing.Net IronBarcode
許可 Apache 2.0(免費) 商業
執行緒安全 非執行緒安全——每個執行緒需要新實例 執行緒安全靜態 API
格式檢測 手動——需要PossibleFormats列表 自動——50 多種格式
PDF 讀取 否——需要 PdfiumViewer 或類似工具 原生——單一方法調用
平台支援 每個平台有單獨的綁定包 單一包,所有平台
每張圖像的多個條碼 是——DecodeMultiple 是——預設行為
條碼生成 返回Bitmap,需要手動保存 具有內建輸出的簡化 API
QR碼標誌支持
QR碼顏色控制
損壞的條碼恢復 TryHarder標誌 ML 驅動的圖像校正
Docker 額外依賴 可能需要libgdiplus None
商業 SLA 支持
需要的 NuGet 包 2-3(核心+綁定+可選ImageSharp) 1

快速開始

步驟1:移除ZXing.Net包

從專案中移除所有ZXing.Net和相關的包:

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

如果本地PdfiumViewer二進制文件作為單獨包安裝:

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

如果Dockerfile包含System.Drawing而新增的——則在遷移後可以移除該行。

步驟2:安裝 IronBarcode

dotnet add package IronBarcode
dotnet add package IronBarcode
SHELL

不需要其他綁定包或平台特定的依賴項。 同一 NuGet 包在 Windows、Linux、macOS 和 Docker 容器中運行。 有關部署詳細資訊,IronBarcode Docker 和 Linux 設置指南涵蓋了具體的 Dockerfile 模板。

步驟3:更新命名空間並初始化授權

從每個使用條碼操作的文件中移除所有ZXing相關命名空間:

// 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

在任何條碼操作之前,在應用程式啟動時新增授權初始化:

// 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

授權金鑰是一個普通字串,可以從環境變數、appsettings.json 或秘密管理器載入。 沒有要定位的文件,也沒有要配置的路徑。

程式碼遷移範例

從圖像中讀取單個條碼

此範例替換了最常見的ZXing.Net使用模式:實例化一個讀取器,配置格式列表,載入位圖並解碼。

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

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

格式列表、using塊全部移除。 IronBarcode直接接受文件路徑並自動檢測所有支持的格式。 以前返回解碼字串的屬性在ZXing.Net中是result.Text; 在IronBarcode中是result.Value

從圖像中讀取所有條碼

此範例代替了DecodeMultiple,在ZXing.Net中需要詳盡的格式列表以避免靜默錯失。

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

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始終返回集合,從不返回null,消除了對結果的空檢查。 要調整準確性與速度的平衡,請參閱讀取速度選項指南,該指南涵蓋了ReadingSpeed枚舉,而不縮小格式範圍。

並行批處理

此範例最直接地顯示了執行緒安全差異。 ZXing.Net需要每個並行操作每次都建立一個新的讀取器; IronBarcode無論並行度如何,都使用相同的靜態調用。

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

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

沒有需要保護或隔離的讀取器實例。 要獲取有關異步管道模式和執行緒數配置的資訊,請參閱異步與多執行緒條碼讀取指南

從PDF中提取條碼

此範例替代了PdfiumViewer渲染迴圈。如果現有整合使用Ghostscript或iText而不是PdfiumViewer,前面部分將在細節上有所不同,但結構上相同:一個頁面枚舉迴圈將位圖餵給ZXing.Net。

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

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

PdfiumViewer依賴項、頁面渲染迴圈、DPI配置、臨時文件建立和清理塊都被刪除。IronBarcode原生讀取PDF中的條碼,自動處理所有頁面。

生成條碼

ZXing.Net寫入器返回一個System.Drawing.Imaging保存。 IronBarcode返回具有內建輸出方法的GeneratedBarcode

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

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

如果需要二進制輸出而不是保存到文件,MemoryStream 管道。

ZXing.Net API到IronBarcode映射參考

ZXing.Net IronBarcode 注意事項
new BarcodeReader() 靜態——無需實例 BarcodeReader.Read(...)是一個靜態調用
`reader.Options.PossibleFormats = new List { ... } 不需要 自動檢測會覆蓋所有50多種格式
reader.Options.TryHarder = true Speed = ReadingSpeed.Balanced 通過BarcodeReaderOptions調整準確性
reader.Decode(bitmap) BarcodeReader.Read(imagePath).FirstOrDefault() 傳遞文件路徑 — 不需要Bitmap建構
reader.DecodeMultiple(bitmap) BarcodeReader.Read(imagePath) 始終返回一個集合; never null
result.Text result.Value 屬性已重命名
result.BarcodeFormat result.Format 屬性已重命名
BarcodeFormat.QR_CODE BarcodeEncoding.QRCode 枚舉命名規範變更
BarcodeFormat.CODE_128 BarcodeEncoding.Code128 枚舉命名規範變更
BarcodeFormat.EAN_13 BarcodeEncoding.EAN13 枚舉命名規範變更
BarcodeFormat.DATA_MATRIX BarcodeEncoding.DataMatrix 枚舉命名規範變更
BarcodeFormat.PDF_417 BarcodeEncoding.PDF417 枚舉命名規範變更
new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... } } BarcodeWriter.CreateBarcode(data, encoding) 靜態工廠,無選項物件
Bitmap .SaveAsPng(path) / .ToPngBinaryData() 內建輸出於GeneratedBarcode
EncodingOptions { Width, Height } |.ResizeTo(width, height)` 流暢尺寸調整方法
無PDF支援 BarcodeReader.Read("file.pdf") 原生PDF支持,所有頁面

常見遷移問題及解決方案

問題1:BarcodeReader實例化模式

ZXing.Net: 呼叫者建立result.Text

解決方案: 完全移除實例化。 用靜態調用替換整個模式:

// 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

在程式碼庫中搜索new BarcodeReader()以找到每個實例。 每一個都被刪除,而不是重構。

問題2:PossibleFormats塊移除

ZXing.Net: 每次解碼調用之前都會有reader.Options.PossibleFormats = new List<BarcodeFormat> { ... }指派。 這些列表通常很長且專案特定。

解決方案: 刪除每個PossibleFormats指定塊的全部。 IronBarcode執行自動格式檢測; 不接受或需要格式列表。 如果BarcodeReaderOptions物件。

問題3:綁定包清理

ZXing.Net: 使用System.Drawing.Bitmap為輸入型別。 使用SixLabors.ImageSharp.Image<Rgba32>。 移除綁定包後,這兩種模式均會中斷。

解決方案: 刪除兩個綁定包並替換所有圖像載入程式碼。 IronBarcode的Image<t>建構。 剩下的Bitmap載入而存在的部分也可以移除。

問題4:result.Text到result.Value

ZXing.Net: 解碼條碼值透過result.Text存取。 條碼格式透過result.BarcodeFormat存取。

解決方案: 替換result.Format。 這兩個更改都是簡單的屬性重命名,沒有行為差別。

ZXing.Net 遷移清單

遷移前任務

在進行變更之前,審查程式碼庫以找到所有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

文件中引用ZXing綁定包的文件(Windows與ImageSharp)中記錄,並註明System.Drawing.Bitmap僅用於ZXing輸入的地方。 審核Dockerfile(如果存在)以確保libgdiplus安裝。

程式碼更新任務

  1. 移除PdfiumViewer NuGet包
  2. 安裝IronBarcode NuGet包
  3. 向應用程式啟動中新增IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
  4. using SixLabors.ImageSharp</em>匯入
  5. 移除每個new BarcodeReader()實例
  6. 刪除每個reader.Options.PossibleFormats = ...
  7. reader.Decode(bitmap)
  8. reader.DecodeMultiple(bitmap)
  9. result.Text
  10. result.BarcodeFormat
  11. 更新BarcodeEncoding.X等效
  12. Replace new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... } }with BarcodeWriter.CreateBarcode(data, encoding).ResizeTo(w, h)
  13. bitmap.Save(...)
  14. 移除所有僅為ZXing.Net位圖載入而存在的using System.Drawing;匯入
  15. 移除任何被實施為PDF替代方法的PdfiumViewer頁面渲染迴圈
  16. 如果它被新增以支持Linux上的libgdiplus

遷移後測試

  • 驗證應用程式先前配置為檢測的每個條碼格式是否成功找到
  • 測試包含先前從PossibleFormats列表中排除掉的條碼格式的圖像,以確認自動檢測能檢出它們
  • 在負載下運行並行處理路徑,並確認沒有競賽條件或空結果
  • 如果應用程式通過PdfiumViewer處理PDF,提供相同的PDF輸入並確認條碼值一致
  • 確認生成的條碼(Code 128、QR 碼等)是否生成了正確的輸出格式和尺寸
  • 在Linux或Docker部署中,確認圖像讀取和PDF讀取是否在沒有libgdiplus的情況下工作
  • 運行完整測試套件並將其輸出與遷移前的基準進行比較

遷移到IronBarcode的主要優勢

消除的執行緒安全負擔: IronBarcode的靜態API完全移除了每執行緒實例模式。 無需實例化讀取器,無需為每個執行緒配置格式列表,無需管理ThreadLocal池。 相同的調用在單執行緒和高併發環境中均正確,併發正確性由庫提供,而不是委派給每個呼叫者。

自動格式檢測: 移除PossibleFormats列表,消除了開發過程中未預見到條碼格式時可能出現的靜默錯失故障。 處理來自外部合作夥伴文件的應用程,或者在不斷演變的條碼標準中運作的應用程式,不再需要進行格式列表維護以保持可靠性。

原生PDF處理: PdfiumViewer渲染迴圈——其頁面枚舉、DPI配置、臨時文件生命周期和清理程式碼——完全被移除。 以前需要兩個函式庫(ZXing.Net 和 PDF 渲染器)才能處理PDF條碼的應用程式現在只需要一個。 已部署依賴項的減少簡化了構建和部署範圍。

單個跨平台包: Windows 和 Linux 部署之間的綁定包區分已被消除。 相同的BarcodeReader.Read(path)調用在所有目標平台上編譯並表現一致,消除了圖像載入程式碼中的平台條件的需求,簡化了跨平台開發和容器化工作流程。

減少了基礎設施程式碼: 遷移最重要的成果是移除了周圍的基礎設施——位圖載入塊、格式列表、PdfiumViewer渲染迴圈、ThreadLocal池——這些都在ZXing.Net 整合中存在,但不涉及到條碼工作,而是繁滿足函式庫的架構要求。 遷移後剩下的就是條碼邏輯本身。 有關檢測率和掃描場景的其他背景,ZXing.Net對比IronBarcode 掃描器比較提供了更廣泛的分析。

請注意Ghostscript, PDFium, ZXing.NET, 和 iText 是其各自所有者的註冊商標。 本網站與 Artifex Software, Chromium Project, Google, ZXing.NET, 或 iText Group 無關,不受其支持或贊助。所有產品名稱、徽標和品牌均為其各自所有者的財產。 比較僅供資訊參考,並反映了撰寫時公開可用的資訊。

常見問題

為什麼我應該從ZXing.Net遷移到IronBarcode?

常見的理由包括簡化授權(去除SDK +運行時鑰匙的複雜性)、消除吞吐量限制、獲得原生PDF支持、改善Docker/CI/CD部署,並減少生產程式碼中的API樣板。

我如何用IronBarcode替換ZXing.Net的API呼叫?

用IronBarCode.License.LicenseKey = "key"替換實例建立和授權樣板。用BarcodeReader.Read(path)替換讀取呼叫,用BarcodeWriter.CreateBarcode(data, encoding)替換寫入呼叫。靜態方法不需要實例管理。

從ZXing.Net遷移到IronBarcode時需要更改多少程式碼?

大多數遷移會導致較少的程式碼行。授權樣板、實例構造函式和顯式格式配置被移除。核心讀/寫操作映射為較短的IronBarcode等價物,且結果物件更清晰。

遷移期間我需要同時安裝ZXing.Net和IronBarcode嗎?

不需要。大多數遷移是直接替換而不是並行操作。一次遷移一個服務類,替換NuGet引用,並更新實例化和API呼叫模式後再移動到下一個類。

IronBarcode的NuGet包名稱是什麼?

包名是'IronBarCode'(大寫B和C)。可以用'Install-Package IronBarCode'或'dotnet add package IronBarCode'安裝。程式碼中的using指令是'using IronBarCode;'。

與ZXing.Net相比,IronBarcode如何簡化Docker的部署?

IronBarcode是沒有外部SDK文件或掛載許可配置的NuGet封裝。在Docker中,設置IRONBARCODE_LICENSE_KEY環境變數,包在啟動時處理許可驗證。

從ZXing.Net遷移後,IronBarcode能自動檢測所有條碼格式嗎?

是的。IronBarcode自動檢測所有支持的格式的符號學。不需要顯式的BarcodeTypes枚舉。如果格式已經知道並且性能很重要,BarcodeReaderOptions允許限制搜索空間作為優化。

IronBarcode是否可以不使用單獨的庫讀取PDF中的條碼?

可以。BarcodeReader.Read("document.pdf")原生處理PDF文件。結果包括每個條碼發現的頁碼、格式、值和置信度。不需要外部PDF渲染步驟。

IronBarcode如何處理並行條碼處理?

IronBarcode的靜態方法是無狀態且執行緒安全的。直接使用Parallel.ForEach遍歷文件列表,不需要每個執行緒的實例管理。BarcodeReaderOptions.MaxParallelThreads控制內部執行緒預算。

從ZXing.Net遷移到IronBarcode時,結果屬性有什麼變化?

常見的重命名:BarcodeValue變為Value,BarcodeType變為Format。IronBarcode結果還新增了Confidence和PageNumber。整個解決方案的搜索和替換可處理現有結果處理程式碼中的重新命名。

我如何在CI/CD管道中設置IronBarcode授權?

將IRONBARCODE_LICENSE_KEY作為管道機密儲存,在應用程式啟動程式碼中分配IronBarCode.License.LicenseKey。一個機密涵蓋所有環境,包括開發、測試、分期和生產。

IronBarcode是否支持生成帶有自定義樣式的QR碼?

支持。QRCodeWriter.CreateQrCode()支持通過ChangeBarCodeColor()自定義顏色,通過AddBrandLogo()嵌入logo,可配置錯誤校正級別,以及包括PNG、JPG、PDF和流在內的多種輸出格式。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

除了開發,Curtis對物聯網(IoT)有濃厚的興趣,探索創新的方法來整合硬體和軟體。在空閒時間,他喜歡玩遊戲和建立Discord機器人,結合他對技術的熱愛與創造力。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話