跳至页脚内容
与其他组件比较

How to Scan Barcodes in ZXing For C# Developers

Accusoft BarcodeXpress与IronBarcode:许可、吞吐量和API权衡

当您通过试用版评估条形码库时,您希望在决定购买之前,先看看它是否真的能在您的图像上正常工作。Accusoft BarcodeXpress不提供该选项。 在评估模式中,解码的条码值被盖上字符串" UNLICENSED accusoft.com ",生成的二维条码也有相同的盖章。您可以验证库是否找到条码,但无法验证其是否正确读取条码。 这是在验证之前就做出承诺的情况,而且在你还没考虑价格之前,就已经造成了一个很大的摩擦点。

了解 Accusoft BarcodeXpress

Accusoft 数十年来一直致力于为Enterprise环境开发文档影像软件。 BarcodeXpress 是 PrizmDoc、ImageGear 和 Accusoft Imaging 等产品系列的一部分。 已经在使用这些产品的团队会遇到熟悉的 API 接口,并且可以利用现有的 Accusoft 账户关系。但对于独立使用条形码的团队来说,这种优势就不那么明显了。

核心 SDK 以NuGet包的形式提供,适用于.NET Core。 API是基于实例的——您需要创建一个writer进行实际操作。 双密钥许可系统使 BarcodeXpress 与大多数替代方案区别开来。

BarcodeXpress 的主要架构特点:

  • 基于实例的API:每个操作都需要BarcodeXpress实例; 静态便捷方法并非设计的一部分
  • 双层许可:SDK许可(SetSolutionName + SetOEMLicenseKey)是不同的系统,需要单独购买。
  • 评估模式盖章:在评估模式中,解码的值被盖上" UNLICENSED accusoft.com "(并且生成的二维条码也有相同的字符串盖章),使得购买前的精度测试变得不可能。
  • 手动格式规范:阅读器需要显式的BarcodeTypes配置来枚举搜索的符号类型; 未指定的格式无法检测到。 -标准版每分钟处理速度上限为 40 页:标准版将处理速度限制为每分钟 40 页,大多数团队在部署后而非部署前会遇到此限制。 -不支持原生 PDF: PDF 文件必须先使用单独的库预渲染成图像,阅读器才能处理它们。 -至少需要五个运行时许可证:即使是单服务器部署也需要购买至少五个运行时许可证。

双钥匙系统详解

BarcodeXpress 将许可分为两个概念上独立的层次:

// BarcodeXpress: two separate license keys required
using Accusoft.BarcodeXpressSdk;

// Constructor takes the path to the runtime files (e.g. ".").
var barcodeXpress = new BarcodeXpress(".");

// Step 1: SDK license (for development).
// SetSolutionName and SetSolutionKey are methods, not properties.
// SetSolutionKey takes four 32-bit integers (not a parsed long).
barcodeXpress.Licensing.SetSolutionName("YourCompanyName");
barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4);

// Step 2: OEM/runtime license (for production — minimum 5 purchased).
try
{
    barcodeXpress.Licensing.SetOEMLicenseKey("YourOEMLicenseString");
}
catch (Exception ex)
{
    // Without a valid OEM license, the SDK runs in stamped evaluation mode.
    Console.WriteLine($"OEM license activation failed: {ex.Message}");
}
// BarcodeXpress: two separate license keys required
using Accusoft.BarcodeXpressSdk;

// Constructor takes the path to the runtime files (e.g. ".").
var barcodeXpress = new BarcodeXpress(".");

// Step 1: SDK license (for development).
// SetSolutionName and SetSolutionKey are methods, not properties.
// SetSolutionKey takes four 32-bit integers (not a parsed long).
barcodeXpress.Licensing.SetSolutionName("YourCompanyName");
barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4);

// Step 2: OEM/runtime license (for production — minimum 5 purchased).
try
{
    barcodeXpress.Licensing.SetOEMLicenseKey("YourOEMLicenseString");
}
catch (Exception ex)
{
    // Without a valid OEM license, the SDK runs in stamped evaluation mode.
    Console.WriteLine($"OEM license activation failed: {ex.Message}");
}
Imports Accusoft.BarcodeXpressSdk

' BarcodeXpress: two separate license keys required

' Constructor takes the path to the runtime files (e.g. ".").
Dim barcodeXpress As New BarcodeXpress(".")

' Step 1: SDK license (for development).
' SetSolutionName and SetSolutionKey are methods, not properties.
' SetSolutionKey takes four 32-bit integers (not a parsed long).
barcodeXpress.Licensing.SetSolutionName("YourCompanyName")
barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4)

' Step 2: OEM/runtime license (for production — minimum 5 purchased).
Try
    barcodeXpress.Licensing.SetOEMLicenseKey("YourOEMLicenseString")
Catch ex As Exception
    ' Without a valid OEM license, the SDK runs in stamped evaluation mode.
    Console.WriteLine($"OEM license activation failed: {ex.Message}")
End Try
$vbLabelText   $csharpLabel

SetSolutionKey对激活SDK本身。 SetOEMLicenseKey调用激活生产部署能力。 两者必须同时存在且有效,才能在生产部署中返回不含" UNLICENSED accusoft.com "盖章的条码值。

在代码审查中,此模式产生了一个可预测的问题:"为什么我们有两个独立的许可激活?" 答案是——Accusoft将SDK许可和部署许可视为独立产品,具有独立的账单安排,这并不是总能从API本身看到的。 团队在初始设置六个月后维护此代码时,通常需要追溯到文档才能了解哪个键对应哪个功能。

没有有效的OEM许可证,SetOEMLicenseKey会抛出异常,SDK会返回至评估模式。 团队通常会将激活包装在try/catch中,以确保故障被大声记录,而不是默默地产生标记值的条形码值:

try
{
    barcodeXpress.Licensing.SetOEMLicenseKey(oemKey);
}
catch (Exception ex)
{
    // In evaluation mode, barcode values are stamped with
    // " UNLICENSED accusoft.com " in the output.
    throw new InvalidOperationException(
        "OEM license activation failed — barcode values will be stamped", ex);
}
try
{
    barcodeXpress.Licensing.SetOEMLicenseKey(oemKey);
}
catch (Exception ex)
{
    // In evaluation mode, barcode values are stamped with
    // " UNLICENSED accusoft.com " in the output.
    throw new InvalidOperationException(
        "OEM license activation failed — barcode values will be stamped", ex);
}
Try
    barcodeXpress.Licensing.SetOEMLicenseKey(oemKey)
Catch ex As Exception
    ' In evaluation mode, barcode values are stamped with
    ' " UNLICENSED accusoft.com " in the output.
    Throw New InvalidOperationException("OEM license activation failed — barcode values will be stamped", ex)
End Try
$vbLabelText   $csharpLabel

当他们意识到评估模式输出默默为结果加上标记而不是在解码时抛出时,团队添加了这种模式:

了解IronBarcode

IronBarcode是一个独立的.NET条形码库,除了其NuGet包之外没有任何外部依赖项。 它通过静态工厂方法处理生成和读取操作,这意味着无需管理实例生命周期,也无需在应用程序代码中散布构造函数调用。

单密钥许可模式意味着您在试用模式下测试的内容就是在生产环境中运行的内容——唯一的区别是试用期间生成的条形码图像上会带有水印。 解码后的值始终是完整的,这意味着您可以在决定是否购买之前,对实际文档的读取准确率进行基准测试。

IronBarcode的主要特点:

  • 静态API设计:BarcodeWriter.CreateBarcode()是无状态的静态方法,无需实例管理 -单一许可证密钥:一个密钥即可同时用于开发和生产部署; 没有单独的运行时许可层 -完整试用值:试用模式返回完整的解码值; 水印仅适用于生成的输出图像,不适用于读取的结果。 -自动格式检测: IronBarcode自动检测所有支持格式的符号体系; 无需BarcodeTypes枚举
  • 原生PDF支持:BarcodeReader.Read("document.pdf")直接处理PDF文件,无需单独的渲染步骤 -无吞吐量上限:处理速度仅受硬件和网络容量限制,不受软件限制。 -线程安全设计:无状态静态方法可以由任意数量的线程并发调用,无需实例隔离。

功能对比

特征 Accusoft BarcodeXpress IronBarcode
许可模式 SDK 许可 + 单独的运行时许可 单永久钥匙
评估模式行为 条形码值标记为"未许可的 accusoft.com" 返回完整值,仅在生成的输出上添加水印
吞吐量限制(标准) 每分钟40页 无吞吐量限制
PDF 支持 需要外部 PDF 库进行图像提取 原生 — BarcodeReader.Read("doc.pdf")
API 风格 基于实例的详细配置 静态工厂方法,流畅 API
线程安全 每个线程一个实例是必需的。 无状态静态方法——自然线程安全
定价切入点 1960 美元以上的 SDK + 2500 美元以上的运行时环境(至少 5 个) 749 美元永久版(Lite,1 位开发者)

详细功能对比

特征 Accusoft BarcodeXpress IronBarcode
许可
许可模式 SDK密钥 + 运行时密钥 单永久钥匙
最低运行时许可 5(即使只有一台服务器) 无运行时许可概念
评估模式 值标记为"未许可的 accusoft.com" 完整数值,仅在输出图像上显示水印
永久许可证 非标准配置——请联系销售 是的,所有级别
年度续订 需要提供支持 可选项
阅读
格式自动检测 手动操作——必须指定条形码类型 所有支持的格式均自动运行
PDF阅读 需要外部 PDF 库 本地
每张图片包含多个条形码 是的,使用BarcodeTypes配置 是的,有ExpectMultipleBarcodes选项
结果属性 BarcodeValue, BarcodeType Value, Format, Confidence, PageNumber
吞吐量限制 40 PPM(标准版) 任何级别均无限制
一代
代码 128 生成 是的,通过writer.BarcodeType 是的,通过BarcodeWriter.CreateBarcode()
二维码生成 是的,通过QRCodeWriter.CreateQrCode()
带有徽标的二维码 需要手动叠加图像 AddBrandLogo("logo.png")内置
输出格式 文件保存 PNG、JPG、PDF、二进制数据、流
平台和部署
.NET Framework 独立的旧版 SDK .NET Framework 4.6.2+
.NET Core / .NET 5+ 是的(.NET Core SDK) .NET Core 3.1+,. .NET 5/6/7/8/9
Linux/Docker 是的——Windows x64/x86、Linux x64、macOS x64/ARM
Docker 许可证配置 许可证文件或许可证服务器 环境变量
CI/CD 集成 需要 SDK 密钥和运行时密钥。 一个秘密
批量处理
螺纹安全 每个线程一个实例是必需的。 无状态 — Parallel.ForEach 安全
并行批处理 需要逐线程实例管理 直接并行。ForEach 支持

许可架构

BarcodeXpress 和IronBarcode在许可复杂性方面的差异在编写将在生产环境中运行的初始化代码时最为明显。

BarcodeXpress 方法

using Accusoft.BarcodeXpressSdk;

public class BarcodeService
{
    private readonly BarcodeXpress _barcodeXpress;

    public BarcodeService()
    {
        _barcodeXpress = new BarcodeXpress(".");

        // Layer 1: SDK license
        _barcodeXpress.Licensing.SetSolutionName("AcmeCorp");
        _barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4);

        // Layer 2: OEM/runtime license — separate purchase, minimum 5
        try
        {
            _barcodeXpress.Licensing.SetOEMLicenseKey("OEMLicenseString");
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException(
                "OEM license activation failed — barcode values will be stamped", ex);
        }
    }
}
using Accusoft.BarcodeXpressSdk;

public class BarcodeService
{
    private readonly BarcodeXpress _barcodeXpress;

    public BarcodeService()
    {
        _barcodeXpress = new BarcodeXpress(".");

        // Layer 1: SDK license
        _barcodeXpress.Licensing.SetSolutionName("AcmeCorp");
        _barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4);

        // Layer 2: OEM/runtime license — separate purchase, minimum 5
        try
        {
            _barcodeXpress.Licensing.SetOEMLicenseKey("OEMLicenseString");
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException(
                "OEM license activation failed — barcode values will be stamped", ex);
        }
    }
}
Imports Accusoft.BarcodeXpressSdk

Public Class BarcodeService
    Private ReadOnly _barcodeXpress As BarcodeXpress

    Public Sub New()
        _barcodeXpress = New BarcodeXpress(".")

        ' Layer 1: SDK license
        _barcodeXpress.Licensing.SetSolutionName("AcmeCorp")
        _barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4)

        ' Layer 2: OEM/runtime license — separate purchase, minimum 5
        Try
            _barcodeXpress.Licensing.SetOEMLicenseKey("OEMLicenseString")
        Catch ex As Exception
            Throw New InvalidOperationException("OEM license activation failed — barcode values will be stamped", ex)
        End Try
    End Sub
End Class
$vbLabelText   $csharpLabel

该构造函数完全用于在任何条形码操作进行之前管理两个独立的许可证激活。 围绕SetOEMLicenseKey的try/catch是必需的——没有它,服务将在任何没有或配置错误的OEM密钥环境中悄悄地返回盖章值。

IronBarcode方法

using IronBarCode;

// In Program.cs or startup configuration
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
using IronBarCode;

// In Program.cs or startup configuration
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
Imports IronBarCode

' In Program.vb or startup configuration
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

这就是完整的许可设置。无需单独的运行时解锁、无需解决方案名称、无需双参数UnlockRuntime调用。 在 Docker 中,这会成为启动时读取的环境变量。在 CI/CD 流水线中,它是一个密钥。 在容器编排器中,它是一个注入到 pod 中的环境变量。

读取条形码

条形码读取揭示了这两个库的配置理念之间的差异——BarcodeXpress 需要显式的格式枚举和基于属性的设置 API,而IronBarcode只需一次方法调用即可自动检测所有内容。

BarcodeXpress 方法

使用BarcodeXpress进行读取需要将图像加载到Analyze(bitmap)以检索结果。 SDK不直接读取PDF - 记录的输入格式是TIFF、JPEG、PNG和BMP:

using Accusoft.BarcodeXpressSdk;
using System.Drawing;

public IEnumerable<string> ReadAllBarcodes(string imagePath)
{
    var barcodeXpress = new BarcodeXpress(".");
    barcodeXpress.Licensing.SetSolutionName("AcmeCorp");
    barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4);
    barcodeXpress.Licensing.SetOEMLicenseKey("OEMLicenseString");

    using var bitmap = new Bitmap(imagePath);

    // BarcodeTypes is a System.Array of BarcodeType values (not a [Flags]
    // enum). Pass Enum.GetValues to scan for everything, or assign a
    // narrower array to restrict the search space.
    barcodeXpress.reader.BarcodeTypes = new[]
    {
        BarcodeType.Code128Barcode,
        BarcodeType.DataMatrixBarcode,
        BarcodeType.QRCodeBarcode
    };

    Result[] results = barcodeXpress.reader.Analyze(bitmap);
    return results.Select(r => r.BarcodeValue);
}
using Accusoft.BarcodeXpressSdk;
using System.Drawing;

public IEnumerable<string> ReadAllBarcodes(string imagePath)
{
    var barcodeXpress = new BarcodeXpress(".");
    barcodeXpress.Licensing.SetSolutionName("AcmeCorp");
    barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4);
    barcodeXpress.Licensing.SetOEMLicenseKey("OEMLicenseString");

    using var bitmap = new Bitmap(imagePath);

    // BarcodeTypes is a System.Array of BarcodeType values (not a [Flags]
    // enum). Pass Enum.GetValues to scan for everything, or assign a
    // narrower array to restrict the search space.
    barcodeXpress.reader.BarcodeTypes = new[]
    {
        BarcodeType.Code128Barcode,
        BarcodeType.DataMatrixBarcode,
        BarcodeType.QRCodeBarcode
    };

    Result[] results = barcodeXpress.reader.Analyze(bitmap);
    return results.Select(r => r.BarcodeValue);
}
Imports Accusoft.BarcodeXpressSdk
Imports System.Drawing

Public Function ReadAllBarcodes(imagePath As String) As IEnumerable(Of String)
    Dim barcodeXpress = New BarcodeXpress(".")
    barcodeXpress.Licensing.SetSolutionName("AcmeCorp")
    barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4)
    barcodeXpress.Licensing.SetOEMLicenseKey("OEMLicenseString")

    Using bitmap As New Bitmap(imagePath)
        ' BarcodeTypes is a System.Array of BarcodeType values (not a [Flags]
        ' enum). Pass Enum.GetValues to scan for everything, or assign a
        ' narrower array to restrict the search space.
        barcodeXpress.Reader.BarcodeTypes = New BarcodeType() {
            BarcodeType.Code128Barcode,
            BarcodeType.DataMatrixBarcode,
            BarcodeType.QRCodeBarcode
        }

        Dim results As Result() = barcodeXpress.Reader.Analyze(bitmap)
        Return results.Select(Function(r) r.BarcodeValue)
    End Using
End Function
$vbLabelText   $csharpLabel

Result[]。 如果文档包含的格式不在BarcodeTypes数组中,将无法找到。 当文档来源发生变化时,这就会成为维护开销。 PDF需要经过单独库的预渲染为图像步骤,然后才能输入到Analyze中。

IronBarcode方法

using IronBarCode;

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

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

Public Function ReadAllBarcodes(imagePath As String) As IEnumerable(Of String)
    Dim results = BarcodeReader.Read(imagePath)
    Return results.Select(Function(r) r.Value)
End Function
$vbLabelText   $csharpLabel

IronBarcode可自动检测所有支持的条码格式。 如果图像包含 Code 128、QR 码和 DataMatrix,则这三个都会在结果集合中返回,无需任何配置更改。 为了更好地控制读取行为, BarcodeReaderOptions类提供了速度、线程数和多条形码设置。

通过相同的方法也可以直接阅读 PDF 文件:

using IronBarCode;

//本地PDF support — no separate library needed
var results = BarcodeReader.Read("invoice-batch.pdf");

foreach (var result in results)
{
    Console.WriteLine($"Page {result.PageNumber}: [{result.Format}] {result.Value}");
}
using IronBarCode;

//本地PDF support — no separate library needed
var results = BarcodeReader.Read("invoice-batch.pdf");

foreach (var result in results)
{
    Console.WriteLine($"Page {result.PageNumber}: [{result.Format}] {result.Value}");
}
Imports IronBarCode

'本地PDF support — no separate library needed
Dim results = BarcodeReader.Read("invoice-batch.pdf")

For Each result In results
    Console.WriteLine($"Page {result.PageNumber}: [{result.Format}] {result.Value}")
Next
$vbLabelText   $csharpLabel

BarcodeXpress 本身并不支持读取 PDF 文件。 您需要先使用单独的库将每一页渲染成图像,然后将这些图像传递给 BarcodeXpress 阅读器。 这会增加一个依赖项,增加一个转换步骤,并且根据所选的 PDF 库,还会增加另一笔许可费用。

批量处理和螺纹安全

大批量条码处理暴露了 BarcodeXpress 的有状态实例模型和IronBarcode的无状态静态 API 之间的架构差异。

BarcodeXpress 方法

BarcodeXpress是基于实例的,其reader对象是有状态的。 并行处理需要每个线程一个实例,并且在每个线程上下文中重复执行完整的双层许可证初始化:

using Accusoft.BarcodeXpressSdk;
using System.Collections.Generic;
using System.Drawing;

public Dictionary<string, string> ProcessBatch(IEnumerable<string> imagePaths)
{
    var results = new Dictionary<string, string>();

    foreach (var path in imagePaths)
    {
        using var bitmap = new Bitmap(path);

        _barcodeXpress.reader.BarcodeTypes = new[]
        {
            BarcodeType.Code128Barcode,
            BarcodeType.QRCodeBarcode
        };

        var barcodes = _barcodeXpress.reader.Analyze(bitmap);
        if (barcodes.Length > 0)
            results[path] = barcodes[0].BarcodeValue;
    }

    return results;
}
using Accusoft.BarcodeXpressSdk;
using System.Collections.Generic;
using System.Drawing;

public Dictionary<string, string> ProcessBatch(IEnumerable<string> imagePaths)
{
    var results = new Dictionary<string, string>();

    foreach (var path in imagePaths)
    {
        using var bitmap = new Bitmap(path);

        _barcodeXpress.reader.BarcodeTypes = new[]
        {
            BarcodeType.Code128Barcode,
            BarcodeType.QRCodeBarcode
        };

        var barcodes = _barcodeXpress.reader.Analyze(bitmap);
        if (barcodes.Length > 0)
            results[path] = barcodes[0].BarcodeValue;
    }

    return results;
}
Imports Accusoft.BarcodeXpressSdk
Imports System.Collections.Generic
Imports System.Drawing

Public Function ProcessBatch(imagePaths As IEnumerable(Of String)) As Dictionary(Of String, String)
    Dim results As New Dictionary(Of String, String)()

    For Each path In imagePaths
        Using bitmap As New Bitmap(path)
            _barcodeXpress.reader.BarcodeTypes = New BarcodeType() {
                BarcodeType.Code128Barcode,
                BarcodeType.QRCodeBarcode
            }

            Dim barcodes = _barcodeXpress.reader.Analyze(bitmap)
            If barcodes.Length > 0 Then
                results(path) = barcodes(0).BarcodeValue
            End If
        End Using
    Next

    Return results
End Function
$vbLabelText   $csharpLabel

标准版还规定每分钟最多只能打印 40 页。 以每分钟 40 页的速度处理 10 万份文件,大约需要 41 小时才能完成。 Professional版取消了这一限制,但每个开发人员的成本更高——此外,还需要支付已购买的运行时许可证费用。

IronBarcode方法

using IronBarCode;
using System.Collections.Concurrent;
using System.Threading.Tasks;

//IronBarcode— parallel batch with thread-safe static API
var files = Directory.GetFiles("/incoming/scans", "*.png");
var allResults = new ConcurrentBag<string>();

Parallel.ForEach(files, file =>
{
    var r = BarcodeReader.Read(file);
    foreach (var barcode in r)
        allResults.Add($"{file}: {barcode.Value}");
});
using IronBarCode;
using System.Collections.Concurrent;
using System.Threading.Tasks;

//IronBarcode— parallel batch with thread-safe static API
var files = Directory.GetFiles("/incoming/scans", "*.png");
var allResults = new ConcurrentBag<string>();

Parallel.ForEach(files, file =>
{
    var r = BarcodeReader.Read(file);
    foreach (var barcode in r)
        allResults.Add($"{file}: {barcode.Value}");
});
Imports IronBarCode
Imports System.Collections.Concurrent
Imports System.Threading.Tasks

'IronBarcode— parallel batch with thread-safe static API
Dim files = Directory.GetFiles("/incoming/scans", "*.png")
Dim allResults = New ConcurrentBag(Of String)()

Parallel.ForEach(files, Sub(file)
    Dim r = BarcodeReader.Read(file)
    For Each barcode In r
        allResults.Add($"{file}: {barcode.Value}")
    Next
End Sub)
$vbLabelText   $csharpLabel

因为IronBarcode的静态方法是无状态的,所以在其之上Parallel.ForEach是安全的,不需要实例隔离。 IronBarcode在任何定价层级都没有吞吐量上限。 为了调整读取性能,BarcodeReaderOptions类提供MaxParallelThreads设置:

using IronBarCode;

var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = true,
    MaxParallelThreads = 4
};

var results = BarcodeReader.Read("warehouse-scan.png", options);
using IronBarCode;

var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = true,
    MaxParallelThreads = 4
};

var results = BarcodeReader.Read("warehouse-scan.png", options);
Imports IronBarCode

Dim options As New BarcodeReaderOptions With {
    .Speed = ReadingSpeed.Balanced,
    .ExpectMultipleBarcodes = True,
    .MaxParallelThreads = 4
}

Dim results = BarcodeReader.Read("warehouse-scan.png", options)
$vbLabelText   $csharpLabel

ReadingSpeed.Balanced是默认值。 使用ReadingSpeed.Detailed用于损坏或低对比度图像。

API 映射参考

Accusoft BarcodeXpress IronBarcode
new BarcodeXpress(".") 静态方法——无需实例
Licensing.SetSolutionName("...") IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
Licensing.SetSolutionKey(int, int, int, int) (removed — not needed)
Licensing.SetOEMLicenseKey(string) (removed — no separate runtime license concept)
在OEM激活时的try/catch (removed — license is always either valid or not)
System.Drawing.Bitmap BarcodeReader.Read(path)
reader.BarcodeTypes = new[] { BarcodeType.Code128Barcode, ... } (removed — auto-detection handles all formats)
result.BarcodeValue result.Value
result.BarcodeType result.Format
writer.BarcodeType = BarcodeType.Code128 BarcodeWriter.CreateBarcode("data", BarcodeEncoding.Code128)
writer.BarcodeValue = "data" (first argument to CreateBarcode)
writer.SaveToFile(path) .SaveAsPng(path)
40 ppm 标准限值 任何层级均无吞吐量限制
评估:值标有"未许可的 accusoft.com" 试用版:完整数值,仅在输出图像上添加水印

当团队考虑从Accusoft BarcodeXpress迁移到IronBarcode

突破 40 PPM 壁垒

标准版每分钟 40 页的限制听起来很慷慨,但当一个业务团队决定对一年的存档发票进行每日批量处理时,就会发现这根本不算什么。 按此速度处理 10 万份文件,大约需要 41 小时才能完成。 升级到Professional版可以取消上限,但每个开发者席位的成本会更高——这还不包括已经购买的运行时许可证。 团队在签署采购订单后发现吞吐量上限,往往会发现解除上限的总成本远远超过最初的估计。

CI/CD 流水线许可复杂性

典型的 CI/CD 设置会在临时容器中运行构建。 使用 BarcodeXpress 时,每个构建环境都需要 SDK 密钥对和运行时解锁密钥,并将它们作为单独的密钥进行管理。 如果运行时密钥缺失或配置错误,构建可能会成功,但集成测试会返回模糊的值——这是一种静默的失败模式,如果测试断言没有针对实际条形码内容仔细编写,则很容易在测试管道中被忽略。

物理隔离和安全部署要求

某些环境——例如处理病人记录的医疗保健系统、政府文件工作流程、金融机构后台处理——不能进行出站网络呼叫的许可证验证。 BarcodeXpress 的运行时许可系统涉及 Accusoft 的许可基础架构,这在网络出口限制严格的环境中可能是一个合规性问题。 在这些环境下工作的团队通常会选择许可证验证完全在本地进行的库。

Docker 和容器部署

在 Docker 中使用 BarcodeXpress 通常需要将许可证文件挂载到容器的已知路径,或者配置许可证服务器并将容器指向该服务器。 这两种方法都会增加部署的复杂性——许可证文件需要分发并保持同步,而且许可证服务器还需要维护额外的基础设施。 团队向微服务架构或无服务器部署模式迁移时发现,配置文件方法无法干净利落地转换为不可变容器镜像。

评估准确性要求

对于需要在购买前验证自身文档读取准确性的团队来说,BarcodeXpress 的评估模式从根本上来说是有限的。 使用真实世界的文档扫描进行测试——检查库是否能处理低对比度条形码、倾斜图像或多条形码页面——需要完整的解码值。 部分遮蔽的输出结果只能显示库找到了条形码,而无法显示它是否正确读取了条形码。

常见迁移注意事项

实例管理到静态调用

BarcodeXpress要求在任何操作之前创建并授权BarcodeXpress实例。IronBarcode的静态方法不需要实例。 迁移的团队通常有一个BarcodeService类,其构造函数主要是许可样板代码——迁移后,该构造函数可以完全删除或简化为单个许可密钥分配。

条形码类型枚举移除

每个BarcodeXpress读操作都需要BarcodeTypes数组分配以枚举搜索的符号类型。 IronBarcode默认会自动检测所有支持的格式。 在迁移过程中,所有reader.BarcodeTypes = ...分配可以被删除而无需替换。 如果有性能原因需要限制搜索空间,BarcodeReaderOptions支持格式过滤作为显式选择加入,而不是必需的默认选项。

结果属性名称更改

两个属性重命名会影响所有结果处理代码:result.Format。 解决方案范围内的搜索和替换功能可以同时处理这两个问题。 IronBarcode结果还公开result.PageNumber,这在BarcodeXpress中没有等效项,可以用于附加过滤,且无需更改现有结果处理代码。

Docker 许可证配置

BarcodeXpress 的 Docker 部署通常使用挂载的许可证配置文件。IronBarcodeIronBarcode使用环境变量。 迁移涉及删除配置文件的COPY指令并添加单个环境变量分配。 在 Kubernetes 中,许可证密钥会成为 pod 规范中的一个秘密引用,而不是一个挂载的卷。

IronBarcode的其他功能

除了本次对比中涵盖的核心功能外, IronBarcode还提供了一些 BarcodeXpress 所不具备的功能:

  • 带Logo的QR码:QRCodeWriter.CreateQrCode().AddBrandLogo("logo.png")本地嵌入品牌形象到QR码中,并且可配置错误校正级别以保持扫描可靠性 -在 PDF 上添加条形码无需单独的 PDF 库,即可直接在现有 PDF 文档上写入条形码。 -批量导出一次性处理整个 PDF 文档,并获取包含页码、格式、值和置信度评分的逐页结果

.NET兼容性和未来准备情况

IronBarcode支持.NET Framework 4.6.2 及更高版本、 .NET Core 3.1 以及.NET 5、6、7、8 和 9。平台目标包括 Windows x64 和 x86、Linux x64 以及 macOS x64 和 ARM。 BarcodeXpress for .NET Core是一个独立于旧版.NET Framework 的SDK——升级应用程序目标框架的团队需要考虑到这一点。IronBarcode的单一软件包涵盖了所有支持的运行时环境。 定期更新跟踪新的.NET版本发布。

结论

BarcodeXpress 和IronBarcode代表了商业.NET条形码库的两种不同设计理念。 BarcodeXpress 将 SDK 访问和生产部署视为单独的许可产品,具有单独的计费方式、单独的密钥系统和单独的最低购买要求。 IronBarcode将该库视为一个单一产品,使用一个密钥即可涵盖从开发到生产的每个环境。

对于已经融入 Accusoft 产品生态系统的团队来说,BarcodeXpress 是一个合理的选择——使用 PrizmDoc 或 ImageGear 的组织会发现 BarcodeXpress 的 API 很熟悉,并且他们与 Accusoft 的帐户关系有助于获得统一的支持。 对于这些车队来说,双密钥许可系统是一种既定的运营模式,而不是新的摩擦。 SDK也适用于文件来源控制良好且格式需求稳定的环境,使得手动BarcodeTypes规格成为可接受的一次性配置,而不是持续维护。

IronBarcode更适合部署到容器、CI/CD 管道和云环境的团队,因为在这些环境中,许可证管理的复杂性会直接影响运营成本。 自动检测模型、静态 API 和原生 PDF 支持减少了集成代码的面积,而单一密钥许可模型简化了跨开发、测试和生产环境的密钥管理。 对于需要在购买前评估读取准确性的团队来说,完整的试验输出(生成的图像上带有水印,而不是读取结果上带有水印)可以实现真正的购买前基准测试。

每个档次的价格差异都很大。 对于单个开发者而言,BarcodeXpress SDKPlus最低运行时许可证与IronBarcode的Lite层级之间存在着相当大的差距。 对于那些将成本差异置于 Accusoft 生态系统集成之上的团队而言,BarcodeXpress 仍然是一个合理的选择。而对于那些仅从条码库本身的性能来评估的团队来说, IronBarcode的评估模式限制、双密钥许可和吞吐量上限等因素,使其成为更直接的选择。

请注意Accusoft是其各自所有者的注册商标。 本网站与Accusoft无隶属关系、背书或赞助。 所有产品名称、徽标和品牌均为各自所有者的财产。 比较仅供参考,反映撰写时公开可用的信息。

常见问题解答

什么是 Accusoft BarcodeXpress?

Accusoft BarcodeXpress 是一个 .NET 条形码库,用于在 C# 应用程序中生成和读取条形码。它是开发人员在为 .NET 项目选择条形码解决方案时评估的几个备选方案之一。

Accusoft BarcodeXpress 和 IronBarcode 的主要区别是什么?

IronBarcode 使用静态、无状态的 API,无需实例管理,而 Accusoft BarcodeXpress 通常需要在使用前创建和配置实例。IronBarcode 还提供原生 PDF 支持、自动格式检测以及跨所有环境的单密钥许可。

IronBarcode 的授权是否比 Accusoft BarcodeXpress 更容易?

IronBarcode 使用单一许可证密钥,同时涵盖开发和生产部署。与将 SDK 密钥与运行时密钥分开的许可系统相比,这简化了 CI/CD 流水线和 Docker 配置。

IronBarcode是否支持Accusoft BarcodeXpress支持的所有条形码格式?

IronBarcode 支持超过 30 种条码符号体系,包括 QR 码、Code 128、Code 39、DataMatrix、PDF417、Aztec、EAN-13、UPC-A、GS1 等等。格式自动检测功能意味着无需显式枚举格式。

IronBarcode是否支持原生PDF条码读取?

是的。IronBarcode 可以直接从 PDF 文件中读取条形码,使用 `BarcodeReader.Read("document.pdf")` 方法,无需单独的 PDF 渲染库。每页的读取结果包括页码、条形码格式、数值和置信度评分。

与 Accusoft BarcodeXpress 相比,IronBarcode 在批量处理方面有何不同?

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 安装程序或运行时文件。

与 Accusoft BarcodeXpress 不同,我可以在购买前评估 IronBarcode 吗?

是的。IronBarcode 的试用模式会返回完整的解码条形码值——只有生成的输出图像才会带有水印。您可以在购买前,用自己的文档测试读取准确率。

Accusoft BarcodeXpress 和 IronBarcode 的价格有什么区别?

IronBarcode 的永久单开发者许可证起价为 749 美元,涵盖开发和生产环境。定价详情和批量许可选项请访问 IronBarcode 许可页面。无需单独的运行时许可证。

从 Accusoft BarcodeXpress 迁移到 IronBarcode 是否简单?

从 Accusoft BarcodeXpress 迁移到 IronBarcode 主要涉及将基于实例的 API 调用替换为 IronBarcode 的静态方法、移除许可相关的样板代码以及更新结果属性名称。大多数迁移工作都是减少代码,而不是增加代码。

IronBarcode 能生成带有 logo 的二维码吗?

是的。`QRCodeWriter.CreateQrCode().AddBrandLogo("logo.png")` 可以将品牌图片原生嵌入二维码中,并支持配置纠错功能。此外,它还支持通过 `ChangeBarCodeColor()` 函数创建彩色二维码。

Curtis Chau
技术作家

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

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

钢铁支援团队

我们每周 5 天,每天 24 小时在线。
聊天
电子邮件
打电话给我