如何使用C#和.NET MAUI读取和扫描条形码
从BarcodeLib迁移到IronBarcode
本指南为.NET开发人员提供了从 条形码库 迁移到IronBarcode 的完整路径。 它涵盖了团队进行这种转变的原因、逐步的软件包替换、每个常见 条形码库 模式的代码迁移示例、完整的 API 映射参考以及用于管理跨代码库迁移的结构化清单。
为什么要从 条形码库 迁移?
从 条形码库 迁移到IronBarcode 的团队报告了以下触发因素:
没有读取 API: 条形码库 从未包含读取或解码功能。 当一个原本生成条形码图像的项目收到新的要求,需要扫描条形码(来自上传的图像、仓库扫描仪或供应商文档)时,BarcodeLib 无法满足这一要求。 唯一的选择是添加第二个库,例如 ZXing .NET,但这会引入第二个依赖关系图和第二个 API 接口,需要与 条形码库 一起维护。
SkiaSharp 版本冲突: 条形码库 3.x 引入了 SkiaSharp 作为图形后端以替代 System.Drawing.Common。 该库仅适用于特定的 SkiaSharp 版本范围。 在 MAUI 项目、 Blazor项目以及任何其他依赖项也引入 SkiaSharp 的项目中,解析后的版本经常超出 条形码库 的预期范围。 这会在恢复期间产生 NU1608 警告,在最坏的情况下,还会导致设备上的运行时程序集绑定失败。
不支持 PDF:生成带有嵌入式条形码的 PDF 文档(例如发票、工作单、发货清单)的应用程序有时需要在下游处理期间读取这些条形码。 条形码库 可以生成条形码图像,但两端均不支持 PDF。 使用 条形码库 从 PDF 中提取条形码需要使用单独的 PDF 库将 PDF 页面渲染成图像,然后将这些图像传递给单独的读取库。
字节数组输出的流编解码步骤: 条形码库 3.x 返回 SKImage,这需要一个 SkiaSharp 编码步骤到 MemoryStream,以生成 HTTP 响应、数据库 BLOB 列和大多数下游消费者实际需要的 byte[] 输出。IronBarcode直接在生成链上提供 .ToPngBinaryData()。
基本问题
BarcodeLib 的仅生成架构意味着,添加任何扫描功能都会强制在堆栈中添加第二个库:
// BarcodeLib: generation only — reading requires a completely separate library
using BarcodeStandard;
using SkiaSharp;
var b = new Barcode();
SKImage img = b.Encode(Type.Code128, "PRODUCT-12345", 300, 100);
using var stream = File.OpenWrite("barcode.png");
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream);
// To read it back, a separate scanning library such as ZXing.Net is required —
// separate API, separate dependency graph to maintain alongside BarcodeLib.
// BarcodeLib: generation only — reading requires a completely separate library
using BarcodeStandard;
using SkiaSharp;
var b = new Barcode();
SKImage img = b.Encode(Type.Code128, "PRODUCT-12345", 300, 100);
using var stream = File.OpenWrite("barcode.png");
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream);
// To read it back, a separate scanning library such as ZXing.Net is required —
// separate API, separate dependency graph to maintain alongside BarcodeLib.
Imports BarcodeStandard
Imports SkiaSharp
Dim b = New Barcode()
Dim img As SKImage = b.Encode(Type.Code128, "PRODUCT-12345", 300, 100)
Using stream = File.OpenWrite("barcode.png")
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream)
End Using
IronBarcode 在同一包中以相同的 using 语句处理两者。
// IronBarcode: generation and reading — no second library needed
using IronBarCode;
// Generate
BarcodeWriter.CreateBarcode("PRODUCT-12345", BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.SaveAsPng("barcode.png");
// Read back — same package, same namespace
var result = BarcodeReader.Read("barcode.png").First().Value;
Console.WriteLine(result); // "PRODUCT-12345"
// IronBarcode: generation and reading — no second library needed
using IronBarCode;
// Generate
BarcodeWriter.CreateBarcode("PRODUCT-12345", BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.SaveAsPng("barcode.png");
// Read back — same package, same namespace
var result = BarcodeReader.Read("barcode.png").First().Value;
Console.WriteLine(result); // "PRODUCT-12345"
Imports IronBarCode
' Generate
BarcodeWriter.CreateBarcode("PRODUCT-12345", BarcodeEncoding.Code128) _
.ResizeTo(300, 100) _
.SaveAsPng("barcode.png")
' Read back — same package, same namespace
Dim result = BarcodeReader.Read("barcode.png").First().Value
Console.WriteLine(result) ' "PRODUCT-12345"
IronBarcode与 BarcodeLib:功能对比
| 特征 | 条形码库 | IronBarcode |
|---|---|---|
| 条形码生成 | 是 | 是 |
| 条形码读取/扫描 | 否 | 是的 (BarcodeReader.Read()) |
| 二维码生成 | 否 (仅限1D) | 是的(高级版,支持嵌入徽标) |
| PDF条形码读取 | 否 | 是的(原生实现,无需额外库) |
| PDF条形码生成输出 | 否 | 是 |
| SkiaSharp 依赖项 | 是的(存在版本冲突风险) | 否 |
| MAUI 项目兼容性 | 冲突风险(NU1608) | 无冲突 |
| 流畅的链式 API | 否 | 是 |
byte[] 直接输出 |
手动 (通过 MemoryStream) |
.ToPngBinaryData() |
| 多条形码检测 | 否 | 是的 (ExpectMultipleBarcodes) |
| 阅读速度调整 | 不适用 | 是的 (ReadingSpeed 枚举) |
| Linux/macOS 支持 | 部分(依赖于 SkiaSharp) | 满的 |
| Docker/容器支持 | 需要配置 | 是 |
| 主动维护 | 是的(社区) | 是的(商业用途) |
| 商业支持/服务水平协议 | 否 | 是 |
| 许可证 | Apache 2.0(免费) | $999–$5,999 永久 |
快速入门:BarcodeLib 到IronBarcode 的迁移
迁移工作可以通过以下基本步骤立即开始。
步骤 1:替换 NuGet 软件包
首先移除BarcodeLib包:
dotnet remove package BarcodeLib
dotnet remove package BarcodeLib
如果您不确定其引用方式,请查看 .csproj 文件:
grep -n "BarcodeLib" YourProject.csproj
grep -n "BarcodeLib" YourProject.csproj
删除所有 条形码库 相关的 <PackageReference> 条目。 如果您添加了显式的 <PackageReference Include="SkiaSharp"> 覆盖以解决来自 条形码库 的 NU1608 警告,也移除那些——安装IronBarcode后,评估 SkiaSharp 是否仍然需要用于其他原因。 然后安装IronBarcode:
dotnet add package IronBarcode
dotnet add package IronBarcode
步骤 2:更新命名空间
在每个引用的文件中替换 条形码库 using 指令:
// Before
using BarcodeStandard;
using SkiaSharp;
// After
using IronBarCode;
// Before
using BarcodeStandard;
using SkiaSharp;
// After
using IronBarCode;
Imports IronBarCode
Imports SkiaSharp
步骤 3:初始化许可证
在应用程序启动时添加许可证初始化:
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
对于 ASP.NET Core 应用程序,将其放在 Program.cs 中,在 builder.Build() 之前。 对于控制台应用程序,将其放在 Main() 的顶部。 对于从其他应用程序调用的类库,请在宿主应用程序启动时对其进行初始化。
代码迁移示例
基本代码128生成
最常见的 条形码库 模式:创建一个实例,设置属性,调用 Encode()。
条形码库方法:
using BarcodeStandard;
using SkiaSharp;
public void GenerateShippingLabel(string trackingNumber, string outputPath)
{
var b = new Barcode();
b.IncludeLabel = true;
SKImage img = b.Encode(Type.Code128, trackingNumber, 400, 120);
using var stream = File.OpenWrite(outputPath);
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream);
}
using BarcodeStandard;
using SkiaSharp;
public void GenerateShippingLabel(string trackingNumber, string outputPath)
{
var b = new Barcode();
b.IncludeLabel = true;
SKImage img = b.Encode(Type.Code128, trackingNumber, 400, 120);
using var stream = File.OpenWrite(outputPath);
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream);
}
Imports BarcodeStandard
Imports SkiaSharp
Public Sub GenerateShippingLabel(trackingNumber As String, outputPath As String)
Dim b As New Barcode()
b.IncludeLabel = True
Dim img As SKImage = b.Encode(Type.Code128, trackingNumber, 400, 120)
Using stream = File.OpenWrite(outputPath)
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream)
End Using
End Sub
IronBarcode方法:
// NuGet: dotnet add package IronBarcode
using IronBarCode;
public void GenerateShippingLabel(string trackingNumber, string outputPath)
{
BarcodeWriter.CreateBarcode(trackingNumber, BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.AddAnnotationTextBelowBarcode(trackingNumber)
.SaveAsPng(outputPath);
}
// NuGet: dotnet add package IronBarcode
using IronBarCode;
public void GenerateShippingLabel(string trackingNumber, string outputPath)
{
BarcodeWriter.CreateBarcode(trackingNumber, BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.AddAnnotationTextBelowBarcode(trackingNumber)
.SaveAsPng(outputPath);
}
Imports IronBarCode
Public Sub GenerateShippingLabel(trackingNumber As String, outputPath As String)
BarcodeWriter.CreateBarcode(trackingNumber, BarcodeEncoding.Code128) _
.ResizeTo(400, 120) _
.AddAnnotationTextBelowBarcode(trackingNumber) _
.SaveAsPng(outputPath)
End Sub
属性设置器块会折叠成一个流畅的链。 .AddAnnotationTextBelowBarcode() 替换 b.IncludeLabel = true — 它明确接受标签字符串,因此您可以控制条形码下方显示的文本。 .ResizeTo() 替换宽度/高度参数。 有关高级生成选项,请参阅IronBarcode条形码生成文档。
返回 byte[] — 常见的 Web API 模式
BarcodeLib 3.x 返回一个 SKImage。 从中获取字节需要通过 SkiaSharp 编码到 MemoryStream。IronBarcode直接提供 .ToPngBinaryData()。
条形码库方法:
using BarcodeStandard;
using SkiaSharp;
using System.IO;
public byte[] GetBarcodeBytes(string data)
{
var b = new Barcode();
SKImage img = b.Encode(Type.Code128, data, 300, 100);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return ms.ToArray();
}
using BarcodeStandard;
using SkiaSharp;
using System.IO;
public byte[] GetBarcodeBytes(string data)
{
var b = new Barcode();
SKImage img = b.Encode(Type.Code128, data, 300, 100);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return ms.ToArray();
}
Imports BarcodeStandard
Imports SkiaSharp
Imports System.IO
Public Function GetBarcodeBytes(data As String) As Byte()
Dim b As New Barcode()
Dim img As SKImage = b.Encode(Type.Code128, data, 300, 100)
Using ms As New MemoryStream()
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms)
Return ms.ToArray()
End Using
End Function
IronBarcode方法:
using IronBarCode;
public byte[] GetBarcodeBytes(string data)
{
return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.ToPngBinaryData();
}
using IronBarCode;
public byte[] GetBarcodeBytes(string data)
{
return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.ToPngBinaryData();
}
Imports IronBarCode
Public Function GetBarcodeBytes(data As String) As Byte()
Return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128) _
.ResizeTo(300, 100) _
.ToPngBinaryData()
End Function
中间步骤 MemoryStream 消失了。 .ToPngBinaryData() 直接返回 byte[],这正是 HTTP 响应主体、数据库 BLOB 列和文件编写器实际需要的。
Web API 控制器操作
条形码库方法:
using BarcodeStandard;
using SkiaSharp;
using Microsoft.AspNetCore.Mvc;
using System.IO;
[ApiController]
[Route("api/labels")]
public class LabelsController : ControllerBase
{
[HttpGet("{sku}")]
public IActionResult GetLabel(string sku)
{
var b = new Barcode();
SKImage img = b.Encode(Type.Code128, sku, 400, 120);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return File(ms.ToArray(), "image/png");
}
}
using BarcodeStandard;
using SkiaSharp;
using Microsoft.AspNetCore.Mvc;
using System.IO;
[ApiController]
[Route("api/labels")]
public class LabelsController : ControllerBase
{
[HttpGet("{sku}")]
public IActionResult GetLabel(string sku)
{
var b = new Barcode();
SKImage img = b.Encode(Type.Code128, sku, 400, 120);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return File(ms.ToArray(), "image/png");
}
}
Imports BarcodeStandard
Imports SkiaSharp
Imports Microsoft.AspNetCore.Mvc
Imports System.IO
<ApiController>
<Route("api/labels")>
Public Class LabelsController
Inherits ControllerBase
<HttpGet("{sku}")>
Public Function GetLabel(sku As String) As IActionResult
Dim b As New Barcode()
Dim img As SKImage = b.Encode(Type.Code128, sku, 400, 120)
Using ms As New MemoryStream()
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms)
Return File(ms.ToArray(), "image/png")
End Using
End Function
End Class
IronBarcode方法:
using IronBarCode;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/labels")]
public class LabelsController : ControllerBase
{
[HttpGet("{sku}")]
public IActionResult GetLabel(string sku)
{
byte[] pngBytes = BarcodeWriter.CreateBarcode(sku, BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.ToPngBinaryData();
return File(pngBytes, "image/png");
}
}
using IronBarCode;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/labels")]
public class LabelsController : ControllerBase
{
[HttpGet("{sku}")]
public IActionResult GetLabel(string sku)
{
byte[] pngBytes = BarcodeWriter.CreateBarcode(sku, BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.ToPngBinaryData();
return File(pngBytes, "image/png");
}
}
Imports IronBarCode
Imports Microsoft.AspNetCore.Mvc
<ApiController>
<Route("api/labels")>
Public Class LabelsController
Inherits ControllerBase
<HttpGet("{sku}")>
Public Function GetLabel(sku As String) As IActionResult
Dim pngBytes As Byte() = BarcodeWriter.CreateBarcode(sku, BarcodeEncoding.Code128) _
.ResizeTo(400, 120) _
.ToPngBinaryData()
Return File(pngBytes, "image/png")
End Function
End Class
通过删除 MemoryStream 块和 SkiaSharp 编码步骤,控制器动作减少了。字节数组直接从 .ToPngBinaryData() 流入 File()。
二维码生成
BarcodeLib 3.x 不生成二维码 — BarcodeStandard.Type 枚举不包含任何二维条目。 需要在BarcodeLib旁边添加QR的项目通常会添加第二个库,如QRCoder。IronBarcode使用一个专用的 QRCodeWriter 类,具有嵌入徽标和样式设置的额外选项。
条形码库方法:
// 条形码库 has no QR Code (or any 2D) support.
// Generating a QR code from a 条形码库 project required adding a
// second library such as QRCoder:
//
// using QRCoder;
// var qrGen = new QRCodeGenerator();
// var data = qrGen.CreateQrCode("https://example.com/product/42", QRCodeGenerator.ECCLevel.Q);
// // ... separate API, separate dependency to maintain.
// 条形码库 has no QR Code (or any 2D) support.
// Generating a QR code from a 条形码库 project required adding a
// second library such as QRCoder:
//
// using QRCoder;
// var qrGen = new QRCodeGenerator();
// var data = qrGen.CreateQrCode("https://example.com/product/42", QRCodeGenerator.ECCLevel.Q);
// // ... separate API, separate dependency to maintain.
' 条形码库 has no QR Code (or any 2D) support.
' Generating a QR code from a 条形码库 project required adding a
' second library such as QRCoder:
'
' Imports QRCoder
' Dim qrGen As New QRCodeGenerator()
' Dim data = qrGen.CreateQrCode("https://example.com/product/42", QRCodeGenerator.ECCLevel.Q)
' ' ... separate API, separate dependency to maintain.
IronBarcode方法:
using IronBarCode;
// Basic QR code
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300)
.SaveAsPng("qr.png");
// QR code with embedded brand logo (not possible with BarcodeLib)
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300)
.AddBrandLogo("logo.png")
.SaveAsPng("qr-branded.png");
using IronBarCode;
// Basic QR code
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300)
.SaveAsPng("qr.png");
// QR code with embedded brand logo (not possible with BarcodeLib)
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300)
.AddBrandLogo("logo.png")
.SaveAsPng("qr-branded.png");
Imports IronBarCode
' Basic QR code
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300) _
.SaveAsPng("qr.png")
' QR code with embedded brand logo (not possible with BarcodeLib)
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300) _
.AddBrandLogo("logo.png") _
.SaveAsPng("qr-branded.png")
QRCodeWriter.CreateQrCode() 接受数据字符串和像素大小作为参数。 徽标嵌入、颜色自定义和错误纠正级别均可通过链式方法实现。 有关二维码样式选项,请参阅IronBarcode二维码文档。
EAN-13 和 UPC-A
这些在零售库存系统中很常见。 枚举名称会改变,但值是完全等效的。
条形码库方法:
using BarcodeStandard;
using SkiaSharp;
// EAN-13 product barcode
var b = new Barcode();
SKImage ean = b.Encode(Type.Ean13, "5901234123457", 250, 100);
using (var s = File.OpenWrite("product-ean.png"))
ean.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s);
// UPC-A for US retail
SKImage upc = b.Encode(Type.UpcA, "012345678905", 250, 100);
using (var s = File.OpenWrite("product-upc.png"))
upc.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s);
using BarcodeStandard;
using SkiaSharp;
// EAN-13 product barcode
var b = new Barcode();
SKImage ean = b.Encode(Type.Ean13, "5901234123457", 250, 100);
using (var s = File.OpenWrite("product-ean.png"))
ean.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s);
// UPC-A for US retail
SKImage upc = b.Encode(Type.UpcA, "012345678905", 250, 100);
using (var s = File.OpenWrite("product-upc.png"))
upc.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s);
Imports BarcodeStandard
Imports SkiaSharp
Imports System.IO
' EAN-13 product barcode
Dim b As New Barcode()
Dim ean As SKImage = b.Encode(Type.Ean13, "5901234123457", 250, 100)
Using s = File.OpenWrite("product-ean.png")
ean.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s)
End Using
' UPC-A for US retail
Dim upc As SKImage = b.Encode(Type.UpcA, "012345678905", 250, 100)
Using s = File.OpenWrite("product-upc.png")
upc.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s)
End Using
IronBarcode方法:
using IronBarCode;
// EAN-13 product barcode
BarcodeWriter.CreateBarcode("5901234123457", BarcodeEncoding.EAN13)
.ResizeTo(250, 100)
.SaveAsPng("product-ean.png");
// UPC-A for US retail
BarcodeWriter.CreateBarcode("012345678905", BarcodeEncoding.UPCA)
.ResizeTo(250, 100)
.SaveAsPng("product-upc.png");
using IronBarCode;
// EAN-13 product barcode
BarcodeWriter.CreateBarcode("5901234123457", BarcodeEncoding.EAN13)
.ResizeTo(250, 100)
.SaveAsPng("product-ean.png");
// UPC-A for US retail
BarcodeWriter.CreateBarcode("012345678905", BarcodeEncoding.UPCA)
.ResizeTo(250, 100)
.SaveAsPng("product-upc.png");
Imports IronBarCode
' EAN-13 product barcode
BarcodeWriter.CreateBarcode("5901234123457", BarcodeEncoding.EAN13) _
.ResizeTo(250, 100) _
.SaveAsPng("product-ean.png")
' UPC-A for US retail
BarcodeWriter.CreateBarcode("012345678905", BarcodeEncoding.UPCA) _
.ResizeTo(250, 100) _
.SaveAsPng("product-upc.png")
新增条形码读取功能(全新功能)
BarcodeLib 没有读取 API。 如果您的迁移是由扫描条形码的新需求驱动的(例如来自上传的图像、仓库扫描仪或扫描的 PDF 文档),则无需添加第二个库即可添加此功能:
条形码库方法:
// 条形码库 — no reading API exists
// Adding reading requires a separate library such as ZXing.Net:
// dotnet add package ZXing.Net
// using ZXing;
// var reader = new BarcodeReader();
// // ... separate API, separate dependency graph to manage
// 条形码库 — no reading API exists
// Adding reading requires a separate library such as ZXing.Net:
// dotnet add package ZXing.Net
// using ZXing;
// var reader = new BarcodeReader();
// // ... separate API, separate dependency graph to manage
' 条形码库 — no reading API exists
' Adding reading requires a separate library such as ZXing.Net:
' dotnet add package ZXing.Net
' Imports ZXing
' Dim reader As New BarcodeReader()
' ' ... separate API, separate dependency graph to manage
IronBarcode方法:
using IronBarCode;
// Read a barcode from an image file
var results = BarcodeReader.Read("incoming-label.png");
foreach (var result in results)
{
Console.WriteLine($"Value: {result.Value}");
Console.WriteLine($"Format: {result.Format}");
}
// Read all barcodes from a multi-page PDF — no PDF library required
var pdfResults = BarcodeReader.Read("supplier-invoice.pdf");
foreach (var result in pdfResults)
{
Console.WriteLine($"Page {result.PageNumber}: {result.Value}");
}
// Configure for high-volume scanning with multiple barcodes per image
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true
};
var warehouseResults = BarcodeReader.Read("dock-scan.png", options);
using IronBarCode;
// Read a barcode from an image file
var results = BarcodeReader.Read("incoming-label.png");
foreach (var result in results)
{
Console.WriteLine($"Value: {result.Value}");
Console.WriteLine($"Format: {result.Format}");
}
// Read all barcodes from a multi-page PDF — no PDF library required
var pdfResults = BarcodeReader.Read("supplier-invoice.pdf");
foreach (var result in pdfResults)
{
Console.WriteLine($"Page {result.PageNumber}: {result.Value}");
}
// Configure for high-volume scanning with multiple barcodes per image
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true
};
var warehouseResults = BarcodeReader.Read("dock-scan.png", options);
Imports IronBarCode
' Read a barcode from an image file
Dim results = BarcodeReader.Read("incoming-label.png")
For Each result In results
Console.WriteLine($"Value: {result.Value}")
Console.WriteLine($"Format: {result.Format}")
Next
' Read all barcodes from a multi-page PDF — no PDF library required
Dim pdfResults = BarcodeReader.Read("supplier-invoice.pdf")
For Each result In pdfResults
Console.WriteLine($"Page {result.PageNumber}: {result.Value}")
Next
' Configure for high-volume scanning with multiple barcodes per image
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True
}
Dim warehouseResults = BarcodeReader.Read("dock-scan.png", options)
BarcodeReader.Read() 接受图像文件、PDF 文件、流和 System.Drawing.Bitmap 对象。 ReadingSpeed 枚举让您可以在大批量扫描时在全面性和性能之间做出权衡。 有关读取配置选项,请参阅IronBarcode读取文档。
解决 SkiaSharp 冲突
如果您的迁移是由 NU1608 警告驱动的,请在切换软件包后验证冲突是否已解决。 在运行 dotnet remove package BarcodeLib 和 dotnet add package IronBarcode 之后,重建并检查输出:
dotnet build 2>&1 | grep -i "NU1608\|SkiaSharp"
dotnet build 2>&1 | grep -i "NU1608\|SkiaSharp"
如果没有输出,则冲突解决。 如果 SkiaSharp 警告仍然存在,则它们来自依赖关系图中的另一个包IronBarcode不是来源。
条形码库方法:
<ItemGroup>
<PackageReference Include="BarcodeLib" Version="3.1.5" />
<PackageReference Include="SkiaSharp" Version="3.116.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BarcodeLib" Version="3.1.5" />
<PackageReference Include="SkiaSharp" Version="3.116.1" />
</ItemGroup>
IronBarcode方法:
<ItemGroup>
<PackageReference Include="IronBarcode" Version="*" />
<PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="3.116.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="IronBarcode" Version="*" />
<PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="3.116.1" />
</ItemGroup>
条形码库 API 到IronBarcode映射参考
| 条形码库 | IronBarcode |
|---|---|
new Barcode() |
静态 API — 无需实例 |
b.Encode(Type.Code128, "data", w, h) |
BarcodeWriter.CreateBarcode("data", BarcodeEncoding.Code128) |
b.IncludeLabel = true |
.AddAnnotationTextBelowBarcode("text") |
宽度/高度传递给 Encode() |
.ResizeTo(width, height) |
返回 SKImage |
.SaveAsPng(path) / .ToPngBinaryData() |
Type.Code128 |
BarcodeEncoding.Code128 |
Type.Code39 |
BarcodeEncoding.Code39 |
Type.Ean13 |
BarcodeEncoding.EAN13 |
Type.UpcA |
BarcodeEncoding.UPCA |
| 无QR支持(仅1D) | BarcodeEncoding.QRCode (also QRCodeWriter) |
Type.Itf14 |
BarcodeEncoding.ITF14 |
Type.Codabar |
BarcodeEncoding.Codabar |
| 无读取 API | BarcodeReader.Read(path) |
| MAUI 中 SkiaSharp 版本冲突 | 没有冲突的依赖项 |
img.Encode(...).SaveTo(stream) |
.SaveAsPng(path) |
MemoryStream + SkiaSharp 编码 |
.ToPngBinaryData() |
常见迁移问题和解决方案
问题1:类型枚举命名空间更改
BarcodeLib 3.x: 使用 BarcodeStandard.Type.Code128 (PascalCase, 在 BarcodeStandard 命名空间中)。 较旧的 2.x 代码可能使用 BarcodeLib.TYPE.CODE128 (大写常量, BarcodeLib 命名空间)——这两种形式都会在迁移中的真实代码库中出现。
解决方案: 替换为 BarcodeEncoding.Code128。 在 .cs 文件中进行 grep,识别所有出现位置:
grep -rn "Type\.\|TYPE\." --include="*.cs" .
grep -rn "Type\.\|TYPE\." --include="*.cs" .
常见替换:Type.Code128 / TYPE.CODE128 → Type.Ean13 / TYPE.EAN13 → Type.UpcA / TYPE.UPCA → Type.Itf14 / TYPE.ITF14 → Type.Codabar / TYPE.CO/DABAR → BarcodeEncoding.Codabar。 BarcodeLib没有QR条目; 任何 TYPE.QR_Code 都是来自 2.x 版本或分叉的死代码 — 替换为 BarcodeEncoding.QRCode (或使用 QRCodeWriter 生成样式化输出)。
问题2:SKImage / Image 返回类型
BarcodeLib: b.Encode() 在 3.x 中返回 SKImage,在 2.x 中返回 System.Drawing.Image。 任何类型都不会在IronBarcode中编译。
解决方案: 移除中间图像变量并用链末端的适当终端方法替换保存逻辑:
// Before (BarcodeLib 3.x)
SKImage img = b.Encode(Type.Code128, data, 300, 100);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return ms.ToArray();
// After
return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.ToPngBinaryData();
// Before (BarcodeLib 3.x)
SKImage img = b.Encode(Type.Code128, data, 300, 100);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return ms.ToArray();
// After
return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.ToPngBinaryData();
Imports System.IO
' Before (BarcodeLib 3.x)
Dim img As SKImage = b.Encode(Type.Code128, data, 300, 100)
Using ms As New MemoryStream()
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms)
Return ms.ToArray()
End Using
' After
Return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128) _
.ResizeTo(300, 100) _
.ToPngBinaryData()
搜索 SKImage img = b.Encode 和 Image img = b.Encode 模式以找到所有受影响的位置。
问题3:宽度和高度参数
BarcodeLib: 在 3.x 中,宽度和高度是 Encode(Type, string, int, int) 上的位置参数,在较旧的 2.x 代码中是单独的 b.Width / b.Height 属性分配。 任一形式均需要移植。
解决方案: 宽度/高度变成单一 .ResizeTo(width, height) 调用链接在 CreateBarcode() 之后。 找到调用站点:
# Find Encode() calls and any Width/Height property assignments
grep -n "\.Encode(\|\.Width = \|\.Height = " --include="*.cs" -r .
# Find Encode() calls and any Width/Height property assignments
grep -n "\.Encode(\|\.Width = \|\.Height = " --include="*.cs" -r .
然后用单一的 .ResizeTo(width, height) 链调用替换尺寸参数或属性对。
问题 4:包含标签布尔开关
BarcodeLib: b.IncludeLabel = true 是一个布尔值,会自动将编码的数据字符串呈现为条形码下方的可见文本。
解决方案: 使用 .AddAnnotationTextBelowBarcode("text"),它以明确的标签字符串为参数。 大多数情况下,传递与条形码中编码的相同的数据字符串。 如果原始代码使用了 IncludeLabel = true 并依赖于 条形码库 自动将数据呈现为标签,请显式传递相同的数据字符串:
BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.AddAnnotationTextBelowBarcode(data) // pass the same string
.SaveAsPng(outputPath);
BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.AddAnnotationTextBelowBarcode(data) // pass the same string
.SaveAsPng(outputPath);
Dim barcodeWriter = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
barcodeWriter.AddAnnotationTextBelowBarcode(data) ' pass the same string
barcodeWriter.SaveAsPng(outputPath)
问题 5:移除 条形码库 后遗留的 SkiaSharp 引用
BarcodeLib: 项目经常积累显式的 <PackageReference Include="SkiaSharp"> 条目,专门用于覆盖 条形码库 的版本限制。 条形码库 移除后,这些文件就变成了孤立文件。
解决方案:切换到IronBarcode后,在移除显式引用之前,请先确认是否还有其他包仍然需要 SkiaSharp:
# Check if SkiaSharp is still referenced by anything other than the explicit override
dotnet list package --include-transitive 2>&1 | grep -i skia
# Check if SkiaSharp is still referenced by anything other than the explicit override
dotnet list package --include-transitive 2>&1 | grep -i skia
如果 SkiaSharp 仅因为已删除的显式 <PackageReference> 出现,请移除该条目。 如果 MAUI 或其他依赖项仍然引入了 IronBarcode,请保留它IronBarcode不会与之冲突。
条形码库 迁移清单
迁移前任务
在开始了解所需变更范围之前,请先运行以下搜索:
# Find all 条形码库 using directives (both 3.x BarcodeStandard and older BarcodeLib)
grep -rn "using BarcodeStandard\|using BarcodeLib" --include="*.cs" .
# Find Barcode object instantiation
grep -rn "new Barcode()" --include="*.cs" .
# Find Encode calls
grep -rn "\.Encode(" --include="*.cs" .
# Find Type enum usage (3.x PascalCase and 2.x uppercase)
grep -rn "Type\.Code128\|Type\.Ean13\|Type\.UpcA\|TYPE\.CODE128\|TYPE\.EAN13\|TYPE\.UPCA" --include="*.cs" .
# Find IncludeLabel usage
grep -rn "IncludeLabel" --include="*.cs" .
# Find the package references in project files
grep -rn "BarcodeLib" --include="*.csproj" .
# Find NU1608 evidence in lock files
grep -rn "NU1608" .
# Find all 条形码库 using directives (both 3.x BarcodeStandard and older BarcodeLib)
grep -rn "using BarcodeStandard\|using BarcodeLib" --include="*.cs" .
# Find Barcode object instantiation
grep -rn "new Barcode()" --include="*.cs" .
# Find Encode calls
grep -rn "\.Encode(" --include="*.cs" .
# Find Type enum usage (3.x PascalCase and 2.x uppercase)
grep -rn "Type\.Code128\|Type\.Ean13\|Type\.UpcA\|TYPE\.CODE128\|TYPE\.EAN13\|TYPE\.UPCA" --include="*.cs" .
# Find IncludeLabel usage
grep -rn "IncludeLabel" --include="*.cs" .
# Find the package references in project files
grep -rn "BarcodeLib" --include="*.csproj" .
# Find NU1608 evidence in lock files
grep -rn "NU1608" .
记录每次搜索影响的所有文件。 请注意哪些项目直接引用 BarcodeLib,哪些项目间接继承了它。 找出所有仅为解决 条形码库 冲突而添加的显式 SkiaSharp 版本覆盖。
代码更新任务
- 为每个项目运行
dotnet remove package BarcodeLib - 删除所有仅为解决 条形码库 冲突而添加的显式 SkiaSharp 版本覆盖引用。
- 为每个项目运行
dotnet add package IronBarcode - 在每个项目的应用程序启动中添加
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"; - 替换
using BarcodeStandard;(或在旧代码中替换using BarcodeLib;) 和using SkiaSharp;为using IronBarCode;,跨所有.cs文件 - 从 2.x
ImageFormat.Png使用中遗留下来的using System.Drawing.Imaging;导入中移除 - 替换
new Barcode()+Encode()调用为BarcodeWriter.CreateBarcode()流畅链 - 替换
Type.Code128/TYPE.CODE128→BarcodeEncoding.Code128和所有其他枚举值 - 替换宽度/高度参数(或2.x版本中的
b.Width = N; b.Height = M;) with `.ResizeTo(N, M) 链调用 - 替换
b.IncludeLabel = true;为.AddAnnotationTextBelowBarcode(data) - 替换
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(...)为.SaveAsPng(path)或.ToPngBinaryData() - 移除中间
SKImage/Image变量和MemoryStream块,.ToPngBinaryData()替换它们 - 在需要的地方添加条形码阅读代码 (
BarcodeReader.Read())
迁移后测试
- 构建项目并确认恢复输出中不再存在任何 NU1608 警告
- 运行
dotnet build 2>&1| grep -i "NU1608|SkiaSharp"` 以验证 SkiaSharp 冲突是否已完全解决 - 将生成的条形码的视觉输出与来自 条形码库 的已知良好样本进行比较。
- 验证二维码使用移动扫描仪或
BarcodeReader.Read()方法正确解码 - 如适用,请使用零售扫描硬件测试 EAN-13 和 UPC-A 条形码。
- 验证图像在所有输出目标(文件系统、HTTP 响应、数据库存储)中是否正确显示
- 使用
BarcodeReader.Read("file.pdf")在真实文档中测试任何 PDF 条形码阅读场景 - 如果项目目标平台是 Linux 或 macOS,请确认跨平台构建成功。
- 验证 MAUI 构建在 Android 和 iOS 目标平台上是否完整,且不存在 SkiaSharp 绑定错误
迁移到IronBarcode的主要优势
无需第二个库即可读取条形码:对于需要读取功能的团队来说,最直接的好处是消除了对第二个库的依赖。 BarcodeReader.Read() 在同一包中,使用相同的 using IronBarCode; 语句,不需要额外的 NuGet 安装。 ZXing .NET及其自身的依赖关系图已不再是该项目的一部分。
没有 SkiaSharp 版本冲突: IronBarcode与应用程序代码不共享 SkiaSharp 依赖关系图。 MAUI 项目、 Blazor项目以及任何多个软件包都汇聚于 SkiaSharp 的项目都可以安装IronBarcode,而不会出现 NU1608 警告或运行时绑定失败。 条形码库 引入的版本协商机制已被移除。
直接字节数组输出: .ToPngBinaryData() 在流畅链的末尾返回 byte[]。 条形码库 需要的输出字节数组的 MemoryStream 中间体被从每个生成条形码的控制器动作、服务方法和 API 处理程序中消除。
PDF 条形码处理: BarcodeReader.Read() 原生接受 PDF 文件。 能够生成带有嵌入式条形码的 PDF 文档的应用程序,无需单独的 PDF 渲染库即可读取这些条形码。 IronBarcode处理了整个流程——生成、PDF 嵌入和读取。
商业支持和SLA: IronBarcode得到Iron Software的商业支持模式的支持,并具有固定的更新节奏。 当新的.NET版本出现或.NET生态系统中出现重大更改时,IronBarcode在与商业SLA相关的时间线上发布兼容性更新,而不是根据社区可用性。
无需第二个库生成二维码: QRCodeWriter 通过链式方法支持徽标嵌入、颜色自定义和纠错级别配置。 条形码库 3.x仅生成1D符号——需要BarcodeLib旁边的QR码的项目通常会添加第二个库,如QRCoder。 QR码需求扩展的团队在同一个包中获得了这些功能,无需改变他们的生成工作流。
常见问题解答
我为什么要从 BarcodeLib 迁移到 IronBarcode?
常见原因包括简化许可(消除 SDK + 运行时密钥的复杂性)、消除吞吐量限制、获得原生 PDF 支持、改进 Docker/CI/CD 部署以及减少生产代码中的 API 样板代码。
如何用 IronBarcode 替换 BarcodeLib API 调用?
用 `IronBarCode.License.LicenseKey = "key"` 替换实例创建和许可相关的样板代码。用 `BarcodeReader.Read(path)` 替换读取器调用,用 `BarcodeWriter.CreateBarcode(data, encoding)` 替换写入器调用。静态方法无需实例管理。
从 BarcodeLib 迁移到 IronBarcode 时,代码需要做多少更改?
大多数迁移都能减少代码行数。许可样板代码、实例构造函数和显式格式配置都被移除。核心读/写操作映射到更简洁的 IronBarcode 等效代码,并生成更清晰的结果对象。
迁移过程中是否需要同时安装 BarcodeLib 和 IronBarcode?
不。大多数迁移都是直接替换,而不是并行操作。一次迁移一个服务类,替换 NuGet 引用,并更新实例化和 API 调用模式,然后再迁移下一个类。
IronBarcode 的 NuGet 包名称是什么?
该软件包名为“IronBarCode”(B 和 C 大写)。使用“Install-Package IronBarCode”或“dotnet add package IronBarCode”进行安装。代码中的 using 指令为“using IronBarCode;”。
与 BarcodeLib 相比,IronBarcode 如何简化 Docker 部署?
IronBarcode 是一个 NuGet 包,不包含任何外部 SDK 文件或已挂载的许可证配置。在 Docker 环境中,设置 IRONBARCODE_LICENSE_KEY 环境变量后,该包会在启动时自动处理许可证验证。
从 BarcodeLib 迁移后,IronBarcode 是否能自动检测所有条形码格式?
是的。IronBarcode 可以自动检测所有支持格式的条码符号,无需显式枚举 BarcodeTypes。如果已知条码格式且性能至关重要,BarcodeReaderOptions 允许缩小搜索范围以进行优化。
IronBarcode 能否在不使用单独库的情况下读取 PDF 中的条形码?
是的。`BarcodeReader.Read("document.pdf")` 可以直接处理 PDF 文件。结果包括每个条形码的页码、格式、值和置信度。无需外部 PDF 渲染步骤。
IronBarcode如何处理并行条码处理?
IronBarcode 的静态方法是无状态且线程安全的。可以直接对文件列表使用 Parallel.ForEach,无需进行线程级实例管理。BarcodeReaderOptions.MaxParallelThreads 控制内部线程预算。
从 BarcodeLib 迁移到 IronBarcode 时,结果属性会发生哪些变化?
常见重命名:BarcodeValue 变为 Value,BarcodeType 变为 Format。IronBarcode 结果还会添加 Confidence 和 PageNumber。解决方案范围内的查找替换功能会处理现有结果处理代码中的重命名。
如何在 CI/CD 流水线中设置 IronBarcode 许可?
将 IRONBARCODE_LICENSE_KEY 存储为管道密钥,并在应用程序启动代码中赋值 IronBarCode.License.LicenseKey。一个密钥即可覆盖所有环境,包括开发、测试、预发布和生产环境。
IronBarcode是否支持生成自定义样式的二维码?
是的。QRCodeWriter.CreateQrCode() 支持通过 ChangeBarCodeColor() 自定义颜色、通过 AddBrandLogo() 嵌入徽标、可配置纠错级别以及多种输出格式,包括 PNG、JPG、PDF 和流媒体。

