IRONSOFTWAREHOME
视频

从ZXing.Net迁移到IronBarcode

Curtis Chau
Curtis Chau
Updated: 2026年8月1日

本指南涵盖了从 ZXing .NET到IronBarcode的完整迁移过程,适用于读取和生成条形码的.NET应用程序。 涉及到移除ZXing.Net的核心包和绑定包,消除PdfiumViewer中的变通方法,并将每个有状态的BarcodeReader实例化替换为IronBarcode的静态API。 每个部分都包含从 ZXing .NET集成中最常见的模式中提取的修改前后的代码。

为什么要从 ZXing .NET迁移?

十多年来,ZXing .NET作为一款免费的 Apache 2.0 条形码库,一直为.NET社区提供优质服务。 然而,随着应用程序规模或复杂性的增长,一些架构限制会转化为运营成本。

**线程安全所有权:**ZXing.Net的BarcodeReader是一个有状态的对象。 该库自身的文档明确指出,实例不能在线程间共享。 实际上,这意味着每个并发处理路径——每个处理并发请求的控制器操作、并行批处理中的每个任务——都必须分配、配置和丢弃自己的读取器。 随着请求量的增加,这种分配模式会产生可衡量的内存压力。 这个ThreadLocal<BarcodeReader>替代方案减少了分配频率,但引入了自身的处置复杂性。 在这两种情况下,并发情况下的正确性都是调用者的问题,而不是库提供的保证。

**格式规范风险:**ZXing.Net需要在每次解码操作前填充reader.Options.PossibleFormats。 在该列表中不存在格式的条码返回空——没有异常、没有警告、没有表明条码存在但未识别的迹象。 对于从外部合作伙伴接收文档的应用程序,这种静默丢失行为是一个可靠性风险:误发的订单、遗漏的患者签到记录或从未写入的审计条目都可能源于为先前要求配置的格式列表且从未更新。

PDF 处理缺陷: ZXing .NET仅读取位图。 当源文档是 PDF 文件(例如发票、装运清单、合规证书)时,调用者必须集成一个单独的 PDF 渲染库(最常见的是 PdfiumViewer),实现页面枚举循环,配置 DPI,管理临时文件,并在成功和失败路径中处理清理工作。 每个集成需要 30 到 50 行基础架构代码,其唯一目的是将 ZXing .NET无法读取的内容(PDF)转换为它可以读取的内容(位图)。 该基础设施有其自身的依赖关系、自身的部署要求和自身的故障模式。

平台绑定碎片化: ZXing.Net 的图像加载功能分散在特定于平台的绑定包中。 Windows绑定使用System.Drawing.Bitmap; 跨平台绑定使用不同泛型类型参数与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;
});

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与 ZXing .NET:功能对比

特征ZXing.NetIronBarcode
执照Apache 2.0(免费)商业翻译
线程安全非线程安全——每个线程都需要一个新的实例。线程安全的静态 API
格式检测手动 — 需要PossibleFormats列表自动 — 50 多种格式
PDF阅读否——需要 PdfiumViewer 或类似软件原生应用 — 单方法调用
平台支持每个平台使用单独的绑定包单一软件包,适用于所有平台
每张图片包含多个条形码是 — DecodeMultiple是的—默认行为
条形码生成返回Bitmap,需要手动保存带有内置输出的流畅 API
支持二维码徽标
二维码颜色控制
条形码损坏恢复TryHarder标志基于机器学习的图像校正
Docker 额外依赖项可能需要libgdiplusNone
商业服务水平协议支持
需要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
SHELL

如果将原生 PdfiumViewer 二进制文件作为单独的软件包安装:

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

如果Dockerfile包含apt-get install -y libgdiplus - 为了通过Linux上的Windows绑定支持System.Drawing而添加 - 在迁移后可以移除该行。

步骤 2:安装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;

在应用程序启动时,在进行任何条形码操作之前,添加许可证初始化:

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

许可证密钥是一个可以从环境变量、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;
}

IronBarcode方法:

using IronBarCode;

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

格式列表、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>();
}

IronBarcode方法:

using IronBarCode;

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

BarcodeReader.Read始终返回一个集合,并且从不返回null,消除了对结果的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);
}

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);
}

没有需要保护或隔离的读取器实例。 有关异步管道模式和线程数配置,请参阅异步和多线程条形码读取指南

从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;
}

IronBarcode方法:

using IronBarCode;

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

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);
}

IronBarcode方法:

using IronBarCode;

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

如果需要二进制输出而不是保存到文件,可以在返回的MemoryStream管道。

ZXing .NET API 到IronBarcode映射参考

ZXing.NetIronBarcode备注
new BarcodeReader()静态 — 无实例BarcodeReader.Read(...)是一个静态调用
reader.Options.PossibleFormats = new List<BarcodeFormat> { ... }不需要自动检测涵盖所有 50 多种格式
reader.Options.TryHarder = trueSpeed = ReadingSpeed.Balanced通过BarcodeReaderOptions进行精度调整
reader.Decode(bitmap)BarcodeReader.Read(imagePath).FirstOrDefault()传递文件路径 — 无需构建Bitmap
reader.DecodeMultiple(bitmap)BarcodeReader.Read(imagePath)始终返回集合; never null
result.Textresult.Value物业已更名
result.BarcodeFormatresult.Format物业已更名
BarcodeFormat.QR_CODEBarcodeEncoding.QRCode枚举命名规则变更
BarcodeFormat.CODE_128BarcodeEncoding.Code128枚举命名规则变更
BarcodeFormat.EAN_13BarcodeEncoding.EAN13枚举命名规则变更
BarcodeFormat.DATA_MATRIXBarcodeEncoding.DataMatrix枚举命名规则变更
BarcodeFormat.PDF_417BarcodeEncoding.PDF417枚举命名规则变更
new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... }BarcodeWriter.CreateBarcode(data, encoding)静态工厂,无选项对象
Bitmap.SaveAsPng(path) / .ToPngBinaryData()内置输出在GeneratedBarcode
EncodingOptions &#123; Width, Height &#125;.ResizeTo(width, height)流畅尺寸测量法
不支持 PDFBarcodeReader.Read("file.pdf")原生支持 PDF,所有页面

常见迁移问题和解决方案

问题 1:条形码读取器实例化模式

**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;

在代码库中搜索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的Uri — 无需构建Image<t>。 其余仅为using System.Drawing;导入也可以删除。

问题 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" .
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. BarcodeReader.Read(imagePath).FirstOrDefault()
  8. BarcodeReader.Read(imagePath)
  9. result.Value
  10. result.Format
  11. 更新BarcodeEncoding.X等效项
  12. 替换 new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... }with BarcodeWriter.CreateBarcode(data, encoding).ResizeTo(w, h)`
  13. writer.Write(data) + .ToPngBinaryData()
  14. 移除所有用于ZXing.Net位图加载的using System.Drawing;导入
  15. 移除所有作为 PDF 变通方案实现的 PdfiumViewer 页面渲染循环。
  16. 从Dockerfile中移除System.Drawing而添加的

迁移后测试

  • 验证应用程序之前配置的每种条形码格式是否都能被成功检测到。
  • 测试包含以前被排除在PossibleFormats列表之外的条码格式的图像,以确认自动检测可以将其拾取
  • 在负载下运行并发处理路径,并确认不存在竞态条件或空结果。
  • 如果应用程序通过 PdfiumViewer 处理 PDF 文件,请提供相同的 PDF 输入文件并确认条形码值是否匹配。
  • 确认生成的条形码(Code 128、QR码等)输出格式和尺寸正确。
  • 在Linux或Docker部署中,确认图像读取和PDF读取在没有libgdiplus的情况下正常工作
  • 运行完整的测试Suite,并将输出结果与迁移前的基线进行比较。

迁移到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无任何关联、认可或赞助。所有产品名称、徽标和品牌均为其各自所有者的财产。 比较仅供参考,反映撰写时公开可用的信息。
Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

...
阅读更多

相关文章

Key in blue circle

立即获取免费的 30 天试用版密钥

Your trial license will be sent to your email address

无任何限制。100% 解锁。无需信用卡。

bullet_checked无需信用卡或创建账户无任何限制。100% 解锁。无需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
预约您的免费现场演示
Booking Badge

深受全球数百万工程师信赖

Iron Software 的客户徽标
获取您的无义务咨询
填写下面的表格或通过sales@ironsoftware.com
您的资料将始终保密。
深受全球数百万工程师信赖
Iron Software 的客户徽标
立即获取您的免费30 天试用密钥
无需信用卡或创建账户