Syncfusion Barcode 与 IronBarcode:C# 条形码库比较
ZXing.Net与IronBarcode:选择2026年.NET条形码库
ZXing.Net的BarcodeReader不是线程安全的。 您的应用程序中每个并发读取路径——每个并行ForEach,每个处理同时请求的异步控制器操作——都需要自己的读取器实例。 这意味着每个实例的格式配置,每次调用的Bitmap加载和释放,以及每个请求的读取器分配。IronBarcode的静态方法在不分配每个请求的情况下处理相同的工作。 线程安全只是其中一项:没有原生 PDF 支持、Windows 和 Linux 上的绑定包碎片化,以及需要指定要扫描的每种条形码格式——这些特性导致 ZXing .NET项目随着时间的推移积累了各种变通方法。
了解.NET
ZXing .NET是 Google Java ZXing("斑马线")库的开源移植版,根据阿帕奇 2.0许可证发布,由 Michael Jahn 在GitHub上维护。 它是下载量最高的.NET开源条形码库,拥有超过十年的悠久历史。 该库涵盖了对多种条形码格式的读取和写入,其零成本许可使其适用于各种规模的项目,包括需要 Apache 兼容依赖项的开源产品。
ZXing.Net 的架构反映了其作为 Java 移植版的起源。 Decode会写入内部状态,这使得实例在不同线程之间共享时不安全。 正确的并发使用需要每个线程一个新的读取器或ThreadLocal<BarcodeReader>池——这两者都将线程安全责任放在调用者身上。 图片加载功能也没有包含在核心软件包中; 相反,ZXing .NET提供特定于平台的绑定包,每个绑定包都公开不同的 API 接口。
主要架构特征包括:
- Apache 2.0 许可证:免费用于商业和开源用途,无需任何费用,也无需联系销售人员。
- 有状态的BarcodeReader:
BarcodeReader实例不是线程安全的; 每个线程或每个并行操作都需要创建一个新的实例。 - 手动格式规范: 调用者必须在每次解码前设置
reader.Options.PossibleFormats; 未列出的格式将被静默跳过,不会出现任何错误或警告。 -不支持原生 PDF:该库仅读取图像; PDF 输入需要单独的 PDF 渲染库(例如 PdfiumViewer)将页面转换为位图,然后再进行解码。 -平台绑定碎片化:核心软件包不提供图像加载; 单独的绑定包(ZXing.Net.Bindings.ImageSharp/.V2/ZXing.Net.Bindings.Magick)为不同的部署目标暴露不同的API。 -活跃的社区: GitHub上存在活跃的问题、拉取请求和讨论,提供免费的社区级支持。 -广泛的格式覆盖范围:支持二维码、Code 128、Code 39、EAN-13、EAN-8、UPC-A、Data Matrix、PDF 417、Aztec 和其他广泛使用的符号体系。
有状态读取器架构
ZXing.Net的BarcodeReader需要为每个线程或并行操作创建一个新实例。 以下模式展示了并发处理的最小正确配置:
// ZXing.Net: a new reader instance is created per iteration
Parallel.ForEach(imagePaths, path =>
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
};
using var bitmap = new Bitmap(path);
var result = reader.Decode(bitmap);
if (result != null)
results[path] = result.Text;
});
// ZXing.Net: a new reader instance is created per iteration
Parallel.ForEach(imagePaths, path =>
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
};
using var bitmap = new Bitmap(path);
var result = reader.Decode(bitmap);
if (result != null)
results[path] = result.Text;
});
Imports System.Collections.Concurrent
Imports System.Drawing
Imports ZXing
Parallel.ForEach(imagePaths, Sub(path)
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(path)
Dim result = reader.Decode(bitmap)
If result IsNot Nothing Then
results(path) = result.Text
End If
End Using
End Sub)
ThreadLocal<BarcodeReader>模式通过每个线程重用一个实例来减少每次调用的分配,但增加了释放的复杂性。 无论哪种方式,线程安全是ZXing.Net中调用者的责任。
了解IronBarcode
IronBarcode是由Iron Software开发的商业.NET条形码库。 它通过无状态静态API提供条码读取和生成:BarcodeWriter.CreateBarcode是主要的入口点,使用前都不需要创建实例或配置。 该库以单个NuGet包的形式发布,可在 Windows、Linux、macOS 和 Docker 容器内以相同的方式运行,无需特定于平台的绑定包。
IronBarcode 的读取引擎可自动检测 50 多种条形码符号体系的格式。 调用者不指定要查找的格式; 引擎会根据所有支持的格式评估每张图片,并返回找到的每个条形码。 对于需要平衡扫描速度和彻底性的应用程序,ExtremeDetail)提供控制,而不需要格式枚举。 该库还包含原生 PDF 支持,可以直接从 PDF 文档的所有页面上读取条形码,而无需单独的 PDF 渲染库。
主要特点包括
-商业许可:需要付费许可密钥; 试用模式可供评估。
- 无状态静态API:
BarcodeWriter.CreateBarcode是线程安全的静态方法; 无需进行实例管理。 -自动格式检测:无需格式列表即可检测所有 50 多种支持的条形码格式;调用者可以调整速度,而不是格式范围。 - 原生PDF支持:
BarcodeReader.Read直接接受PDF文件路径,处理所有页面,无需外部PDF库。 -单一跨平台包:一个NuGet包可在 Windows、Linux、macOS 和 Docker 上运行,并具有相同的 API 接口。 - 流畅生成API:
ToStream。 -商业支持:付费许可证包含获得 Iron Software 支持团队的服务级别承诺。
功能对比
下表列出了 ZXing .NET和IronBarcode之间的根本区别:
| 特征 | ZXing.Net | IronBarcode |
|---|---|---|
| 执照 | Apache 2.0(免费) | 商业翻译 |
| 线程安全 | 非线程安全——每个线程都需要一个新的实例。 | 线程安全的静态 API |
| 格式检测 | 手动—需要PossibleFormats列表 |
自动 — 50 多种格式 |
| PDF阅读 | 否——需要 PdfiumViewer 或类似软件 | 原生应用 — 单方法调用 |
| 平台支持 | 每个平台使用单独的绑定包 | 单一软件包,适用于所有平台 |
| 条形码生成 | 返回Bitmap,需要手动保存 |
带有内置输出的流畅 API |
| 定价 | 免费 | 从$749(Lite)/$1,499(Plus) |
详细功能对比
| 特征 | ZXing.Net | IronBarcode |
|---|---|---|
| 阅读 | ||
| 线程安全读取 | 不需要——每个线程都需要实例 | 是的——静态无状态 API |
| 自动格式检测 | 否—需要PossibleFormats |
是的——所有格式都能自动检测 |
| 每张图片包含多个条形码 | 是—DecodeMultiple |
是的——默认行为 |
| PDF条形码读取 | 否——需要外部库 | 是的——本地人 |
| 条形码损坏恢复 | TryHarder标志 |
基于机器学习的图像校正 |
| 速度/精度调校 | 格式列表缩减 | ReadingSpeed枚举 |
| 一代 | ||
| 代码 128 / 代码 39 | 是 | 是 |
| 二维码 | 是 | 是 |
| 带有徽标的二维码 | 否 | 是 |
| 二维码颜色定制 | 否 | 是 |
| 输出格式为 PNG/JPEG/PDF | 通过System.Drawing手动 |
内置输出方法 |
| 流畅的生成链 | 否 | 是 |
| 平台和部署 | ||
| Windows(System.Drawing) | 是—ZXing.Net.Bindings.Windows.Compatibility |
是 |
| Linux / Docker | 是—ZXing.Net.Bindings.ImageSharp / .V2 / .V3(不同API) |
是的——同样的API |
| MacOS | 是—ZXing.Net.Bindings.ImageSharp / .V2 / .V3 |
是 |
| Docker 额外依赖项 | 可能需要libgdiplus |
None |
| 单个 NuGet 软件包 | 否 — 核心 + 绑定 + 可选 ImageSharp | 是 |
| 许可和支持 | ||
| 许可证类型 | 阿帕奇 2.0 | 商业翻译 |
| 成本 | 免费 | 749美元起 |
| 社区支持 | GitHub问题,活跃的社区 | 是 |
| 商业服务水平协议支持 | 否 | 是 |
| 对开源友好 | 是 | 否 |
线程安全和并发处理
线程安全是这两个库之间最重要的操作差异,它影响的项目比文档警告所暗示的要多。
ZXing .NET方法
ZXing.Net的BarcodeReader是一个有状态对象。 当调用Decode时,内部状态被写入。 如果两个线程共享同一个实例,则会发生写入竞争。 结果不确定:您可能会得到来自不同图像的结果、条形码存在时为空的结果,或者出现异常。 正确的做法是为每个线程创建一个读取器——这意味着每个并行或异步路径都会分配一个读取器,对其进行配置,使用一次,然后将其丢弃:
// ZXing.Net: one reader instance per parallel operation
Parallel.ForEach(imagePaths, path =>
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
};
using var bitmap = new Bitmap(path);
var result = reader.Decode(bitmap);
if (result != null)
results[path] = result.Text;
});
// ZXing.Net: one reader instance per parallel operation
Parallel.ForEach(imagePaths, path =>
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
};
using var bitmap = new Bitmap(path);
var result = reader.Decode(bitmap);
if (result != null)
results[path] = result.Text;
});
Imports System.Collections.Concurrent
Imports System.Drawing
Imports ZXing
Parallel.ForEach(imagePaths, Sub(path)
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(path)
Dim result = reader.Decode(bitmap)
If result IsNot Nothing Then
results(path) = result.Text
End If
End Using
End Sub)
ThreadLocal<BarcodeReader>模式通过每个线程重用一个读取器来减小每调用分配,但这增加了释放的复杂性,每个实例仍需要格式配置。
IronBarcode方法
IronBarcode的BarcodeReader.Read是一个无状态的静态方法。 没有需要共享的实例,没有需要隔离的实例,也没有需要保护的配置状态。 同一个调用可以从任意数量的并发线程中安全运行:
// IronBarcode: static method — no instance management
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true,
MaxParallelThreads = 4
};
Parallel.ForEach(imagePaths, path =>
{
var result = BarcodeReader.Read(path, options).FirstOrDefault();
if (result != null)
results[path] = result.Value;
});
// IronBarcode: static method — no instance management
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true,
MaxParallelThreads = 4
};
Parallel.ForEach(imagePaths, path =>
{
var result = BarcodeReader.Read(path, options).FirstOrDefault();
if (result != null)
results[path] = result.Value;
});
Imports IronBarcode
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True,
.MaxParallelThreads = 4
}
Parallel.ForEach(imagePaths, Sub(path)
Dim result = BarcodeReader.Read(path, options).FirstOrDefault()
If result IsNot Nothing Then
results(path) = result.Value
End If
End Sub)
IronBarcode 的异步和多线程条形码读取文档解释了内部线程池模型。 MaxParallelThreads属性无需外部协调即可控制并行度。
格式检测
格式检测策略是这两个库之间第二个重要的操作差异。
ZXing .NET方法
ZXing.Net要求在每次解码之前填充reader.Options.PossibleFormats。 如果条形码格式未列出,则无法检测到——不会报错、不会警告、也不会给出部分结果:
// ZXing.Net: PossibleFormats list controls which symbologies are decoded
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);
// ZXing.Net: PossibleFormats list controls which symbologies are decoded
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);
Imports ZXing
Imports ZXing.Common
' ZXing.Net: PossibleFormats list controls which symbologies are decoded
Dim reader As 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)
End Using
如果列出所有格式以避免遗漏,性能会下降。 如果只列出预期格式,当图像来自外部来源时,就会出现静默缺失的风险。 ZXing .NET没有机制来报告它发现了未列出格式的条形码。
IronBarcode方法
IronBarcode可自动检测所有 50 多种受支持的格式。 无需也不接受任何格式列表:
// IronBarcode: automatic detection across all supported formats
var results = BarcodeReader.Read(imagePath);
foreach (var barcode in results)
{
Console.WriteLine($"{barcode.Value} ({barcode.Format})");
}
// IronBarcode: automatic detection across all supported formats
var results = BarcodeReader.Read(imagePath);
foreach (var barcode in results)
{
Console.WriteLine($"{barcode.Value} ({barcode.Format})");
}
Imports IronBarcode
' IronBarcode: automatic detection across all supported formats
Dim results = BarcodeReader.Read(imagePath)
For Each barcode In results
Console.WriteLine($"{barcode.Value} ({barcode.Format})")
Next
对于需要在读取速度与检测彻底性之间进行调整的应用程序,IronBarcode公开了一个ExtremeDetail——无需格式枚举。 速度调优影响的是引擎处理每张图像的积极程度,而不是它考虑的图像格式。
PDF 文档支持
ZXing .NET无法读取 PDF 文件:该库没有任何形式的 PDF 支持。
ZXing .NET方法
当条形码嵌入在 PDF 文件中时,ZXing .NET需要一个外部 PDF 渲染库。 最常见的解决方法是使用 PdfiumViewer,但这会增加大约 20 MB 的本地二进制文件和一个页面渲染循环,调用者必须实现和维护这些文件和循环:
// ZXing.Net: PDF input is handled by PdfiumViewer with a per-page render loop
using var pdfDocument = PdfDocument.Load(pdfPath);
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.PDF_417
};
for (int i = 0; i < pdfDocument.PageCount; i++)
{
string tempPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png");
try
{
using var pageImage = pdfDocument.Render(i, 200, 200, PdfRenderFlags.CorrectFromDpi);
pageImage.Save(tempPath, ImageFormat.Png);
using var bitmap = new Bitmap(tempPath);
var decoded = reader.DecodeMultiple(bitmap);
if (decoded != null)
results.AddRange(decoded.Select(d => d.Text));
}
finally
{
File.Delete(tempPath);
}
}
// ZXing.Net: PDF input is handled by PdfiumViewer with a per-page render loop
using var pdfDocument = PdfDocument.Load(pdfPath);
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.PDF_417
};
for (int i = 0; i < pdfDocument.PageCount; i++)
{
string tempPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png");
try
{
using var pageImage = pdfDocument.Render(i, 200, 200, PdfRenderFlags.CorrectFromDpi);
pageImage.Save(tempPath, ImageFormat.Png);
using var bitmap = new Bitmap(tempPath);
var decoded = reader.DecodeMultiple(bitmap);
if (decoded != null)
results.AddRange(decoded.Select(d => d.Text));
}
finally
{
File.Delete(tempPath);
}
}
Imports System.IO
Imports System.Drawing
Imports PdfiumViewer
Imports ZXing
Imports ZXing.Common
' ZXing.Net: PDF input is handled by PdfiumViewer with a per-page render loop
Using pdfDocument As PdfDocument = PdfDocument.Load(pdfPath)
Dim reader As New BarcodeReader()
reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.PDF_417
}
For i As Integer = 0 To pdfDocument.PageCount - 1
Dim tempPath As String = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png")
Try
Using pageImage As Image = pdfDocument.Render(i, 200, 200, PdfRenderFlags.CorrectFromDpi)
pageImage.Save(tempPath, Imaging.ImageFormat.Png)
Using bitmap As New Bitmap(tempPath)
Dim decoded = reader.DecodeMultiple(bitmap)
If decoded IsNot Nothing Then
results.AddRange(decoded.Select(Function(d) d.Text))
End If
End Using
End Using
Finally
File.Delete(tempPath)
End Try
Next
End Using
这种模式存在一些实际的故障模式:DPI 配置错误会导致静默失败,临时文件权限在受限环境中会失效,PdfiumViewer 本地库需要单独的部署管理,并且如果没有额外的配置,该设置在 Linux 上无法工作。
IronBarcode方法
IronBarcode可以直接从 PDF 中读取条形码——支持所有页面、所有格式,无需外部依赖。 相同的BarcodeReader.Read调用直接接受PDF路径:
// IronBarcode: one call processes every page of the PDF
var results = BarcodeReader.Read("invoice.pdf");
foreach (var barcode in results)
Console.WriteLine($"Page {barcode.PageNumber}: {barcode.Value}");
// IronBarcode: one call processes every page of the PDF
var results = BarcodeReader.Read("invoice.pdf");
foreach (var barcode in results)
Console.WriteLine($"Page {barcode.PageNumber}: {barcode.Value}");
Imports IronBarcode
' IronBarcode: one call processes every page of the PDF
Dim results = BarcodeReader.Read("invoice.pdf")
For Each barcode In results
Console.WriteLine($"Page {barcode.PageNumber}: {barcode.Value}")
Next
没有页面枚举,没有 DPI 配置,没有临时文件,也没有与应用程序一起部署的单独库。
平台绑定和部署
ZXing.Net 的图像处理分布在特定于平台的绑定包中,每个包都有不同的 API 接口。
ZXing .NET方法
核心ZXing.Net包提供解码逻辑,但不加载图像。 调用者必须根据其部署目标选择绑定:
| 环境 | 包裹 | 备注 |
|---|---|---|
| Windows桌面/WPF | ZXing.Net.Bindings.Windows.Compatibility |
使用System.Drawing—友好的Windows; 在Linux上需要libgdiplus |
| Linux / Docker/ 跨平台 | ZXing.Net.Bindings.ImageSharp / .V2 / .V3 |
不同的API接口; 添加SixLabors.ImageSharp依赖(V2/V3跟踪ImageSharp主要版本) |
| MacOS | ZXing.Net.Bindings.ImageSharp / .V2 / .V3 |
与 Linux 相同的路径 |
实际后果是,使用System.Drawing.Bitmap的Windows代码无法在Linux上编译或运行。 容器化需要切换绑定包并重写镜像加载代码:
// Windows binding path — uses System.Drawing
using ZXing.Windows.Compatibility;
using System.Drawing;
var reader = new BarcodeReader();
using var bitmap = new Bitmap(imagePath);
var result = reader.Decode(bitmap);
// Windows binding path — uses System.Drawing
using ZXing.Windows.Compatibility;
using System.Drawing;
var reader = new BarcodeReader();
using var bitmap = new Bitmap(imagePath);
var result = reader.Decode(bitmap);
Imports ZXing.Windows.Compatibility
Imports System.Drawing
Dim reader As New BarcodeReader()
Using bitmap As New Bitmap(imagePath)
Dim result = reader.Decode(bitmap)
End Using
// Cross-platform path — different package, different API
using ZXing.ImageSharp;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
var reader = new BarcodeReader<Rgba32>();
using var image = Image.Load<Rgba32>(imagePath);
var result = reader.Decode(image);
// Cross-platform path — different package, different API
using ZXing.ImageSharp;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
var reader = new BarcodeReader<Rgba32>();
using var image = Image.Load<Rgba32>(imagePath);
var result = reader.Decode(image);
Imports ZXing.ImageSharp
Imports SixLabors.ImageSharp
Imports SixLabors.ImageSharp.PixelFormats
Dim reader As New BarcodeReader(Of Rgba32)()
Using image As Image(Of Rgba32) = Image.Load(Of Rgba32)(imagePath)
Dim result = reader.Decode(image)
End Using
在Linux主机上使用Windows绑定还需要在Docker镜像中添加libgdiplus,增加大约50 MB到容器。
IronBarcode方法
IronBarcode为所有平台提供统一的软件包。 相同的BarcodeReader.Read(path)调用在Windows、Linux、macOS和Docker容器内部编译和运行完全相同。 无需绑定软件包,无需平台条件,也无需额外的系统依赖项。 对于将.NET应用程序容器化的团队, IronBarcode Docker 和 Linux 设置指南详细介绍了单包部署模式。
生成 API
这两个库都能生成条形码,但它们的 API 体现了不同的设计方法。
ZXing .NET方法
ZXing.Net的System.Drawing.Imaging手动保存:
// ZXing.Net: create writer, set options, call Write, save Bitmap
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using System.Drawing.Imaging;
var writer = new BarcodeWriter
{
Format = BarcodeFormat.CODE_128,
Options = new EncodingOptions
{
Width = 300,
Height = 100,
Margin = 10
}
};
using var bitmap = writer.Write("PRODUCT-001");
bitmap.Save("output.png", ImageFormat.Png);
// ZXing.Net: create writer, set options, call Write, save Bitmap
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using System.Drawing.Imaging;
var writer = new BarcodeWriter
{
Format = BarcodeFormat.CODE_128,
Options = new EncodingOptions
{
Width = 300,
Height = 100,
Margin = 10
}
};
using var bitmap = writer.Write("PRODUCT-001");
bitmap.Save("output.png", ImageFormat.Png);
Imports ZXing
Imports ZXing.Common
Imports ZXing.Windows.Compatibility
Imports System.Drawing.Imaging
Dim writer As New BarcodeWriter With {
.Format = BarcodeFormat.CODE_128,
.Options = New EncodingOptions With {
.Width = 300,
.Height = 100,
.Margin = 10
}
}
Using bitmap = writer.Write("PRODUCT-001")
bitmap.Save("output.png", ImageFormat.Png)
End Using
保存到PNG或JPEG以外的其他格式、保存到PDF或为HTTP响应生成二进制输出都需要调用者实现额外的System.Drawing设置。
IronBarcode方法
IronBarcode的GeneratedBarcode对象,通过流畅的链提供内建输出方法:
// IronBarcode: create and save in one fluent chain
BarcodeWriter.CreateBarcode("PRODUCT-001", BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.SaveAsPng("output.png");
// IronBarcode: create and save in one fluent chain
BarcodeWriter.CreateBarcode("PRODUCT-001", BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.SaveAsPng("output.png");
Imports IronBarCode
' IronBarcode: create and save in one fluent chain
BarcodeWriter.CreateBarcode("PRODUCT-001", BarcodeEncoding.Code128) _
.ResizeTo(300, 100) _
.SaveAsPng("output.png")
System.Drawing。
API 映射参考
| ZXing.Net | IronBarcode | 备注 |
|---|---|---|
new BarcodeReader() |
静态 — 无实例 | BarcodeReader.Read(...)是一个静态调用 |
reader.Options.PossibleFormats = new List<BarcodeFormat> { ... } |
不需要 | 自动检测涵盖所有格式 |
reader.Options.TryHarder = true |
Speed = ReadingSpeed.Balanced |
通过BarcodeReaderOptions进行精确度调整 |
reader.Decode(bitmap) |
BarcodeReader.Read(imagePath) |
直接传递路径—不需要Bitmap |
reader.DecodeMultiple(bitmap) |
BarcodeReader.Read(imagePath) |
始终返回集合 |
result.Text |
result.Value |
物业已更名 |
result.BarcodeFormat |
result.Format |
物业已更名 |
BarcodeFormat.QR_CODE |
BarcodeEncoding.QRCode |
枚举命名规则变更 |
BarcodeFormat.CODE_128 |
BarcodeEncoding.Code128 |
枚举命名规则变更 |
BarcodeFormat.EAN_13 |
BarcodeEncoding.EAN13 |
枚举命名规则变更 |
new BarcodeWriter { Format = BarcodeFormat.CODE_128, Options = new EncodingOptions { ... }|BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)` |
静态工厂方法 | |
Bitmap |
.SaveAsPng(path) / .ToPngBinaryData() |
内建输出方法在GeneratedBarcode上 |
| 不支持 PDF——需要 PdfiumViewer | BarcodeReader.Read("doc.pdf") |
原生 PDF 支持 |
| 不线程安全 | 线程安全的静态 API | 无需实例管理 |
当团队考虑从 ZXing .NET迁移到IronBarcode时
多种场景促使开发团队评估IronBarcode作为 ZXing .NET的替代方案。
并发高吞吐量处理
在单线程控制台应用程序中运行正常的 ZXing .NET集成,当相同的代码移至处理并发请求的ASP.NET Core控制器或并行处理批处理的后台作业中时,可能会表现出不确定的行为。 ZXing .NET要求的线程实例模式意味着每个请求或并行任务都会分配一个完整的读取器对象及其配置的解码器集,使用一次后将其丢弃。 随着请求量的增长,这种分配压力变得可以衡量。 达到这一步的团队——特别是那些在物流、仓储或文档处理中运行高吞吐量扫描管道的团队——通常会寻找一个线程模型不会给每个调用者带来这种开销的库。
混合格式文档扫描
接受第三方文档的应用程序经常会遇到在配置格式列表时未预料到的条形码格式。 为 Code 128 构建的物流集成系统使用二维码接收来自合作伙伴的货物。 配置为 PDF 417 的医疗记录系统遇到了来自新设备供应商的 Data Matrix 符号体系。 在 ZXing .NET中,这些情况都会产生静默的空值而不是解码错误,这意味着直到下游处理失败,错误才会显现出来。 那些曾因静默格式错误而遭受损失的团队——尤其是在条形码错误造成业务后果的情况下——开始权衡格式列表维护的成本与能够自动检测格式的库的成本。
PDF条形码提取
许多商业文件都是以 PDF 格式提供的:发票、发货清单、病人记录、合规证书。 .NET无法直接读取这些文件。 需要从 PDF 中提取条形码的团队最终会在 ZXing .NET之上构建和维护渲染管道——选择 PDF 库、管理其原生依赖项、实现页面渲染循环、处理 DPI 配置以及编写临时文件的清理逻辑。 该基础设施代码并非条形码逻辑; 它存在的唯一目的就是弥合 ZXing .NET接受的内容(位图)与业务文档实际内容(PDF)之间的差距。 维护这座桥梁的团队(尤其是当 PDF 库本身有其自身的许可、部署和平台方面的考虑因素时)通常更喜欢使用能够处理整个输入界面的单一库。
降低绑定复杂性
在 Windows 上启动,然后部署到 Linux 或 Docker 的项目会直接遇到 ZXing.Net 的绑定碎片化问题:Windows 绑定包使用的 API 与跨平台 ImageSharp 绑定使用的 API 不同,在它们之间切换需要同时更改NuGet引用和图像加载代码。 那些习惯性地将.NET应用程序容器化的团队,或者在开发人员机器(Windows 或 macOS)和生产服务器(Linux)上运行相同代码库的团队发现,维护两条用于图像加载的代码路径会给扫描层未来的每一次更改带来摩擦。
常见迁移注意事项
从 ZXing .NET过渡到IronBarcode 的团队应该针对这些具体的技术变化做好规划。
条形码阅读器实例化移除
代码库中每个new BarcodeReader()调用在迁移过程中被移除。 实例化模式——读取器创建、格式配置、图像加载、解码调用——可以简化为一个静态方法调用。 导入using IronBarCode;。
可能的格式配置移除
ReadingSpeed属性,它控制检测努力无需缩小格式范围。
绑定包清理
迁移移除了.V2 / PdfiumViewer包。 如果System.Drawing,那行也会被移除。 IronBarcode在 Docker 镜像中不需要任何平台特定的依赖项。
IronBarcode的其他功能
除了以上对比部分介绍的功能外, IronBarcode还提供:
-带有徽标嵌入的二维码:生成带有自定义徽标图像叠加在中心的二维码,并具有自动纠错功能,以确保可扫描性。
- 二维码颜色自定义:设置生成的二维码的前景色和背景色,以实现品牌一致性输出。 -在 PDF 上添加条形码:无需单独的 PDF 库,即可将条形码直接写入现有 PDF 页面的指定坐标。
- GS1 条码支持:读取和生成 GS1 格式的条码,包括 GS1-128 和 GS1 DataBar,用于零售和医疗保健供应链。
- 多线程异步读取: 内建异步方法,便于将条码读取集成到
await流水线中而不阻塞。 - 基于ML的图像校正: 自动增强对损坏、模糊或低对比度条码图像的处理,
TryHarder无法恢复。
.NET兼容性和未来准备情况
IronBarcode 针对 .NET Standard 2.0 及以上版本,提供与 .NET Framework 4.6.2+、.NET Core 3.1、.NET 5、.NET 6、.NET 7、.NET 8 和 .NET 9 的兼容性。库将根据 Microsoft 的 .NET 发布周期定期更新,以确保在 .NET 10 发布时提供兼容性。 ZXing .NET也通过其NuGet包目标保持了广泛的.NET兼容性,从这个角度来看,这两个库都适用于现代.NET项目。
结论
ZXing .NET和IronBarcode代表了条形码库设计的不同理念。 ZXing .NET是一个有状态的、基于实例的库,它将线程责任、格式规范和 PDF 桥接完全委托给调用者。 IronBarcode是一个无状态的静态 API 库,它内部实现了线程处理,自动检测格式,并原生处理 PDF 输入。 这种差异带来的实际后果是,在并发或文档处理环境中,ZXing .NET代码往往会积累基础架构——每个线程的实例模式、格式列表、PDF 渲染管道和特定于平台的绑定分支——而IronBarcode在相同场景下的代码则不需要这些外围结构。
对于零成本要求的项目来说,ZXing .NET确实是一个非常不错的选择。 其阿帕奇 2.0许可证使其与开源项目以及偏好免费依赖项的商业产品兼容。 对于受控环境(已知条形码格式、清晰图像、单线程或轻度并发处理),它能够可靠地运行。 其活跃的GitHub社区能够及时响应问题,并且其格式覆盖范围可与商业替代方案相媲美。 对于满足这些条件的应用场景,ZXing.Net 的成本优势是实实在在的,其技术局限性也是可以克服的。
IronBarcode解决了 ZXing.Net 的设计约束转化为运营成本的场景:并发 Web API(其中每个请求的实例分配是可衡量的)、文档管道(其中 PDF 输入是常态而不是例外)、混合格式扫描(其中静默失败会带来业务风险)以及跨平台部署(其中两个绑定包意味着两条代码路径)。 在这些情况下,该库的商业许可购买了无需实例管理的线程模型、无需维护的格式检测以及无需第二个库的 PDF 支持。
该决定取决于项目的具体需求。 对于单一格式原型、开源扫描器或成本是主要限制因素的小批量工具而言,ZXing .NET是合适的选择。而对于跨多个线程处理来自外部来源文档的生产级 Web API 而言,IronBarcode 的设计理念则更符合实际运行情况。 为了更全面地了解这些库在检测率和实际扫描场景方面的比较情况, ZXing .NET与IronBarcode条形码扫描器比较提供了更多分析。
常见问题解答
ZXing.Net是什么?
ZXing.Net 是一个 .NET 条形码库,用于在 C# 应用程序中生成和读取条形码。它是开发人员在为 .NET 项目选择条形码解决方案时评估的几个备选方案之一。
ZXing.Net 和 IronBarcode 的主要区别是什么?
IronBarcode 使用静态、无状态的 API,无需实例管理,而 ZXing.Net 通常需要在使用前创建和配置实例。IronBarcode 还提供原生 PDF 支持、自动格式检测以及跨所有环境的单密钥许可。
IronBarcode 的授权比 ZXing.Net 更容易吗?
IronBarcode 使用单一许可证密钥,同时涵盖开发和生产部署。与将 SDK 密钥与运行时密钥分开的许可系统相比,这简化了 CI/CD 流水线和 Docker 配置。
IronBarcode是否支持ZXing.Net支持的所有条形码格式?
IronBarcode 支持超过 30 种条码符号体系,包括 QR 码、Code 128、Code 39、DataMatrix、PDF417、Aztec、EAN-13、UPC-A、GS1 等等。格式自动检测功能意味着无需显式枚举格式。
IronBarcode是否支持原生PDF条码读取?
是的。IronBarcode 可以直接从 PDF 文件中读取条形码,使用 `BarcodeReader.Read("document.pdf")` 方法,无需单独的 PDF 渲染库。每页的读取结果包括页码、条形码格式、数值和置信度评分。
IronBarcode 与 ZXing.Net 相比,在批量处理方面有何不同?
IronBarcode 的静态方法是无状态的,并且天然线程安全,因此可以直接使用 Parallel.ForEach,而无需进行线程级实例管理。所有定价层级均无吞吐量上限。
IronBarcode支持哪些.NET版本?
IronBarcode 在单个 NuGet 包中支持 .NET Framework 4.6.2+、.NET Core 3.1 以及 .NET 5、6、7、8 和 9。平台目标包括 Windows x64/x86、Linux x64 和 macOS x64/ARM。
如何在.NET项目中安装IronBarcode?
通过 NuGet 安装 IronBarcode:在程序包管理器控制台中运行“Install-Package IronBarCode”,或在命令行界面中运行“dotnet add package IronBarCode”。无需其他 SDK 安装程序或运行时文件。
与 ZXing.Net 不同,我可以在购买前评估 IronBarcode 吗?
是的。IronBarcode 的试用模式会返回完整的解码条形码值——只有生成的输出图像才会带有水印。您可以在购买前,用自己的文档测试读取准确率。
ZXing.Net 和 IronBarcode 的价格有什么区别?
IronBarcode 的永久单开发者许可证起价为 749 美元,涵盖开发和生产环境。定价详情和批量许可选项请访问 IronBarcode 许可页面。无需单独的运行时许可证。
从 ZXing.Net 迁移到 IronBarcode 是否简单?
从 ZXing.Net 迁移到 IronBarcode 主要涉及将基于实例的 API 调用替换为 IronBarcode 的静态方法、移除许可相关的样板代码以及更新结果属性名称。大多数迁移工作都是减少代码,而不是增加代码。
IronBarcode 能生成带有 logo 的二维码吗?
是的。`QRCodeWriter.CreateQrCode().AddBrandLogo("logo.png")` 可以将品牌图片原生嵌入二维码中,并支持配置纠错功能。此外,它还支持通过 `ChangeBarCodeColor()` 函数创建彩色二维码。

