Migrating from ZXing.Net to IronBarcode
ZXing.NetからIronBarcodeへの移行
このガイドでは、バーコードの読み取りと生成を行う.NETアプリケーション向けに、ZXing .NETからIronBarcodeへの完全な移行手順を説明します。 ZXing.Netのコアパッケージとバインディングパッケージの削除、存在する場合のPdfiumViewerのワークアラウンドの排除、およびすべてのステートフルなBarcodeReaderのインスタンスをIronBarcodeの静的APIに置き換えます。 各セクションには、ZXing for .NET統合で最もよく見られるパターンから抽出した、変更前と変更後のコードが含まれています。
ZXing .NETから移行する理由
ZXing .NETは、無料のApache 2.0バーコードライブラリとして、10年以上にわたり.NETコミュニティに貢献してきました。 しかし、アプリケーションの規模や複雑さが増すにつれて、いくつかのアーキテクチャ上の制約が運用コストへと転じる。
スレッドセーフティ所有: ZXing.NetのBarcodeReaderは状態を持つオブジェクトです。 ライブラリの公式ドキュメントには、インスタンスはスレッド間で共有してはならないと明記されている。 実際には、これは、同時処理パス(同時リクエストを処理するコントローラアクション、並列バッチ内のタスクなど)ごとに、独自のリーダーを割り当て、構成し、破棄する必要があることを意味します。 リクエスト量が増加するにつれて、この割り当てパターンは測定可能なメモリ負荷を生み出す。 ThreadLocal<BarcodeReader>の代替案は割り当て頻度を減少させますが、そのための廃棄の複雑性を導入します。 どちらの場合も、並行処理における正しさは呼び出し側の責任であり、ライブラリが提供する保証ではありません。
フォーマット仕様リスク: ZXing.Netは各デコード操作の前にreader.Options.PossibleFormatsが埋められている必要があります。 そのリストに存在しないフォーマットのバーコードはnullを返します — 例外も警告も、バーコードが存在していたが認識されなかったという指示もありません。 外部パートナーからドキュメントを受け取るアプリケーションにとって、このサイレントミスの振る舞いは信頼性のリスクです: 誤配送された注文、患者のチェックイン記録の見逃し、記録されない監査エントリはすべて、以前の要件用に設定され更新されなかったフォーマットリストから発生する可能性があります。
PDF処理のギャップ: ZXing .NETはビットマップしか読み取れません。 ソースドキュメントがPDF(請求書、出荷明細書、コンプライアンス証明書など)の場合、呼び出し元は別途PDFレンダリングライブラリ(最も一般的なのはPdfiumViewer)を統合し、ページ列挙ループを実装し、DPIを設定し、一時ファイルを管理し、成功時と失敗時の両方でクリーンアップ処理を行う必要があります。 これは、ZXing .NETが読み取れないもの(PDF)を、読み取れるもの(ビットマップ)に変換するためだけに存在する、統合ごとに30~50行のインフラストラクチャコードです。 そのインフラストラクチャには、独自の依存関係、独自の導入要件、そして独自の障害モードが存在する。
プラットフォームバインディングの断片化: ZXing.Netの画像読み込み機能は、プラットフォーム固有のバインディングパッケージに分散しています。 WindowsのバインディングはSystem.Drawing.Bitmapを使用します。 クロスプラットフォームのバインディングは異なるジェネリックタイプパラメータと異なるSixLabors.ImageSharpを使用します。Windowsで開始し、後でLinuxでコンテナ化するプロジェクトは、NuGetの参照と画像読み込みのコードの両方を変更する必要があります。 同じ操作に対して2つのコードパスが存在すると、バグが発生する可能性が高まり、スキャンレイヤーの将来的な変更に対する障壁が増加する。
基本的な問題
ZXing .NETアーキテクチャを最も明確に示しているのは、シングルスレッド呼び出しと並行呼び出しの間のギャップである。 ZXing .NETでは、並行処理を行うには、並列操作ごとに完全なリーダーオブジェクトを作成する必要があります。
// ZXing.Net: full reader instantiation and configuration on every parallel task
Parallel.ForEach(files, file =>
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
};
using var bitmap = new Bitmap(file);
var result = reader.Decode(bitmap);
if (result != null)
processed[file] = result.Text;
});
// ZXing.Net: full reader instantiation and configuration on every parallel task
Parallel.ForEach(files, file =>
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
};
using var bitmap = new Bitmap(file);
var result = reader.Decode(bitmap);
if (result != null)
processed[file] = result.Text;
});
Imports ZXing
Imports System.Drawing
Imports System.Threading.Tasks
Parallel.ForEach(files, Sub(file)
Dim reader As New BarcodeReader()
reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
}
Using bitmap As New Bitmap(file)
Dim result = reader.Decode(bitmap)
If result IsNot Nothing Then
processed(file) = result.Text
End If
End Using
End Sub)
IronBarcodeはオブジェクトを完全に削除します。 静的呼び出しは、1つのスレッドで実行されても、100のスレッドで実行されても同じです。
// IronBarcode: static call, same code for single-threaded and concurrent use
Parallel.ForEach(files, file =>
{
var result = BarcodeReader.Read(file).FirstOrDefault();
if (result != null)
processed[file] = result.Value;
});
// IronBarcode: static call, same code for single-threaded and concurrent use
Parallel.ForEach(files, file =>
{
var result = BarcodeReader.Read(file).FirstOrDefault();
if (result != null)
processed[file] = result.Value;
});
Imports IronBarCode
Imports System.Threading.Tasks
Parallel.ForEach(files, Sub(file)
Dim result = BarcodeReader.Read(file).FirstOrDefault()
If result IsNot Nothing Then
processed(file) = result.Value
End If
End Sub)
IronBarcodeとZXing .NET:機能比較
| フィーチャー | ZXing.Net | IronBarcode |
|---|---|---|
| ライセンス | アパッチ2.0(無料) | 商用 |
| スレッドセーフティ | スレッドセーフではありません。スレッドごとに新しいインスタンスが必要です。 | スレッドセーフな静的API |
| フォーマット検出 | 手動 — PossibleFormatsリストが必要です |
自動 — 50種類以上のフォーマット |
| PDFリーディング | いいえ — PdfiumViewerまたは同様のツールが必要です | ネイティブ — 単一メソッド呼び出し |
| プラットフォームサポート | プラットフォームごとに個別のバインディングパッケージ | 単一パッケージ、全プラットフォーム対応 |
| 画像ごとに複数のバーコード | はい — DecodeMultiple |
はい — デフォルトの振る舞いです |
| バーコード生成 | Bitmapを返し、手動で保存が必要です |
組み込み出力機能を備えた流暢なAPI |
| QRコードロゴのサポート | なし | はい |
| QRコードの色管理 | なし | はい |
| 破損したバーコードの復旧 | TryHarderフラグ |
機械学習を活用した画像補正 |
| Dockerの追加依存関係 | libgdiplusが必要になる場合があります |
None |
| 商用SLAサポート | なし | はい |
| 必要なNuGetパッケージ | 2~3(コア+バインディング+オプションのImageSharp) | 1 |
クイックスタート
ステップ1:ZXing .NETパッケージを削除する
プロジェクトからすべてのZXing .NETおよび関連パッケージを削除します。
dotnet remove package ZXing.Net
dotnet remove package ZXing.Net.Bindings.Windows.Compatibility
dotnet remove package ZXing.Net.Bindings.ImageSharp
dotnet remove package PdfiumViewer
dotnet remove package ZXing.Net
dotnet remove package ZXing.Net.Bindings.Windows.Compatibility
dotnet remove package ZXing.Net.Bindings.ImageSharp
dotnet remove package PdfiumViewer
ネイティブのPdfiumViewerバイナリが別のパッケージとしてインストールされた場合:
dotnet remove package PdfiumViewer.Native.x64.v8-xfa
dotnet remove package PdfiumViewer.Native.x64.v8-xfa
DockerfileにSystem.Drawingのサポートのために追加された)、移行後にその行を削除できます。
ステップ2: IronBarcodeをインストールする
dotnet add package IronBarcode
dotnet add package IronBarcode
追加のバインディングパッケージやプラットフォーム固有の依存関係は必要ありません。 同じNuGetパッケージは、Windows、Linux、macOS、および Docker コンテナ内で動作します。 デプロイの詳細については、 IronBarcodeのDockerおよびLinuxセットアップガイドに、具体的なDockerfileのパターンが記載されています。
ステップ3:名前空間を更新し、ライセンスを初期化する
バーコード操作を使用するすべてのファイルから、ZXing関連の名前空間をすべて削除してください。
// Remove all of these:
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using ZXing.ImageSharp;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using PdfiumViewer;
// Add this single import:
using IronBarCode;
// Remove all of these:
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using ZXing.ImageSharp;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using PdfiumViewer;
// Add this single import:
using IronBarCode;
Imports IronBarCode
アプリケーションの起動時、バーコード操作の前にライセンスの初期化処理を追加してください。
// Program.cs or Startup.cs — initialise once at startup
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
// Program.cs or Startup.cs — initialise once at startup
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
' Program.vb or Startup.vb — initialise once at startup
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
ライセンスキーは環境変数、appsettings.json、またはシークレットマネージャーからロードできる単純な文字列です。 探すべきファイルも、設定すべきパスもありません。
コード移行の例
画像から単一のバーコードを読み取る
この例では、最も一般的な ZXing .NETの使用パターン、つまりリーダーのインスタンス化、フォーマット リストの設定、ビットマップの読み込み、デコードという手順を置き換えます。
ZXing .NETアプローチ:
using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;
public string ReadSingleBarcode(string imagePath)
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
};
using var bitmap = new Bitmap(imagePath);
var result = reader.Decode(bitmap);
return result?.Text ?? string.Empty;
}
using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;
public string ReadSingleBarcode(string imagePath)
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
};
using var bitmap = new Bitmap(imagePath);
var result = reader.Decode(bitmap);
return result?.Text ?? string.Empty;
}
Imports ZXing
Imports ZXing.Windows.Compatibility
Imports System.Drawing
Public Function ReadSingleBarcode(imagePath As String) As String
Dim reader = New BarcodeReader()
reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
}
Using bitmap As New Bitmap(imagePath)
Dim result = reader.Decode(bitmap)
Return If(result?.Text, String.Empty)
End Using
End Function
IronBarcodeのアプローチ:
using IronBarCode;
public string ReadSingleBarcode(string imagePath)
{
var result = BarcodeReader.Read(imagePath).FirstOrDefault();
return result?.Value ?? string.Empty;
}
using IronBarCode;
public string ReadSingleBarcode(string imagePath)
{
var result = BarcodeReader.Read(imagePath).FirstOrDefault();
return result?.Value ?? string.Empty;
}
Imports IronBarCode
Public Function ReadSingleBarcode(imagePath As String) As String
Dim result = BarcodeReader.Read(imagePath).FirstOrDefault()
Return If(result?.Value, String.Empty)
End Function
フォーマットリスト、usingのブロックがすべて削除されます。 IronBarcodeはファイルパスを直接受け付け、サポートされているすべてのフォーマットを自動的に検出します。 以前デコードされた文字列を返していたプロパティはZXing.Netのresult.Textでした。 それはIronBarcodeのresult.Valueです。
画像からすべてのバーコードを読み取る
この例はDecodeMultipleを置き換えます。ZXing.Netではサイレントミスを避けるために徹底したフォーマットリストが必要です。
ZXing .NETアプローチ:
using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;
public List<string> ReadAllBarcodes(string imagePath)
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.CODE_39,
BarcodeFormat.EAN_13,
BarcodeFormat.EAN_8,
BarcodeFormat.UPC_A,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.PDF_417
};
reader.Options.TryHarder = true;
using var bitmap = new Bitmap(imagePath);
var results = reader.DecodeMultiple(bitmap);
return results?.Select(r => r.Text).ToList() ?? new List<string>();
}
using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;
public List<string> ReadAllBarcodes(string imagePath)
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.CODE_39,
BarcodeFormat.EAN_13,
BarcodeFormat.EAN_8,
BarcodeFormat.UPC_A,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.PDF_417
};
reader.Options.TryHarder = true;
using var bitmap = new Bitmap(imagePath);
var results = reader.DecodeMultiple(bitmap);
return results?.Select(r => r.Text).ToList() ?? new List<string>();
}
Imports ZXing
Imports ZXing.Windows.Compatibility
Imports System.Drawing
Public Function ReadAllBarcodes(imagePath As String) As List(Of String)
Dim reader = New BarcodeReader()
reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.CODE_39,
BarcodeFormat.EAN_13,
BarcodeFormat.EAN_8,
BarcodeFormat.UPC_A,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.PDF_417
}
reader.Options.TryHarder = True
Using bitmap As New Bitmap(imagePath)
Dim results = reader.DecodeMultiple(bitmap)
Return If(results?.Select(Function(r) r.Text).ToList(), New List(Of String)())
End Using
End Function
IronBarcodeのアプローチ:
using IronBarCode;
public List<string> ReadAllBarcodes(string imagePath)
{
return BarcodeReader.Read(imagePath)
.Select(r => r.Value)
.ToList();
}
using IronBarCode;
public List<string> ReadAllBarcodes(string imagePath)
{
return BarcodeReader.Read(imagePath)
.Select(r => r.Value)
.ToList();
}
Imports IronBarCode
Public Function ReadAllBarcodes(imagePath As String) As List(Of String)
Return BarcodeReader.Read(imagePath) _
.Select(Function(r) r.Value) _
.ToList()
End Function
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);
}
using ZXing;
using ZXing.Windows.Compatibility;
using System.Collections.Concurrent;
using System.Drawing;
public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
var output = new ConcurrentDictionary<string, string>();
Parallel.ForEach(filePaths, new ParallelOptions { MaxDegreeOfParallelism = 4 }, file =>
{
// ZXing.Net is not thread-safe — a new reader is required per parallel operation
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128
};
using var bitmap = new Bitmap(file);
var result = reader.Decode(bitmap);
if (result != null)
output[file] = result.Text;
});
return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
Imports ZXing
Imports ZXing.Windows.Compatibility
Imports System.Collections.Concurrent
Imports System.Drawing
Public Function ProcessBatch(filePaths As IEnumerable(Of String)) As Dictionary(Of String, String)
Dim output = New ConcurrentDictionary(Of String, String)()
Parallel.ForEach(filePaths, New ParallelOptions With {.MaxDegreeOfParallelism = 4}, Sub(file)
' ZXing.Net is not thread-safe — a new reader is required per parallel operation
Dim reader = New BarcodeReader()
reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128
}
Using bitmap As New Bitmap(file)
Dim result = reader.Decode(bitmap)
If result IsNot Nothing Then
output(file) = result.Text
End If
End Using
End Sub)
Return output.ToDictionary(Function(kvp) kvp.Key, Function(kvp) kvp.Value)
End Function
IronBarcodeのアプローチ:
using IronBarCode;
using System.Collections.Concurrent;
public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
var output = new ConcurrentDictionary<string, string>();
var options = new BarcodeReaderOptions { MaxParallelThreads = 4 };
Parallel.ForEach(filePaths, file =>
{
var result = BarcodeReader.Read(file, options).FirstOrDefault();
if (result != null)
output[file] = result.Value;
});
return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
using IronBarCode;
using System.Collections.Concurrent;
public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
var output = new ConcurrentDictionary<string, string>();
var options = new BarcodeReaderOptions { MaxParallelThreads = 4 };
Parallel.ForEach(filePaths, file =>
{
var result = BarcodeReader.Read(file, options).FirstOrDefault();
if (result != null)
output[file] = result.Value;
});
return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
Imports IronBarCode
Imports System.Collections.Concurrent
Public Function ProcessBatch(filePaths As IEnumerable(Of String)) As Dictionary(Of String, String)
Dim output = New ConcurrentDictionary(Of String, String)()
Dim options = New BarcodeReaderOptions With {.MaxParallelThreads = 4}
Parallel.ForEach(filePaths, Sub(file)
Dim result = BarcodeReader.Read(file, options).FirstOrDefault()
If result IsNot Nothing Then
output(file) = result.Value
End If
End Sub)
Return output.ToDictionary(Function(kvp) kvp.Key, Function(kvp) kvp.Value)
End Function
保護または隔離すべきリーダーインスタンスは存在しません。 非同期パイプラインのパターンとスレッド数の設定については、"非同期およびマルチスレッドのバーコード読み取りガイド"を参照してください。
PDFファイルからバーコードを抽出する
この例はPdfiumViewerレンダーループを置き換えています。既存の統合がPdfiumViewerの代わりにGhostscriptやiTextを使用していた場合、前のブロックは詳細は異なりますが、構造は同一です: ページ列挙ループがビットマップをZXing.Netに供給します。
ZXing .NETアプローチ:
using ZXing;
using ZXing.Windows.Compatibility;
using PdfiumViewer;
using System.Drawing;
using System.Drawing.Imaging;
public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
var collected = new List<string>();
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.PDF_417
};
using var document = PdfDocument.Load(pdfPath);
for (int page = 0; page < document.PageCount; page++)
{
string temp = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png");
try
{
using var rendered = document.Render(page, 200, 200, PdfRenderFlags.CorrectFromDpi);
rendered.Save(temp, ImageFormat.Png);
using var bmp = new Bitmap(temp);
var decoded = reader.DecodeMultiple(bmp);
if (decoded != null)
collected.AddRange(decoded.Select(d => d.Text));
}
finally
{
if (File.Exists(temp))
File.Delete(temp);
}
}
return collected;
}
using ZXing;
using ZXing.Windows.Compatibility;
using PdfiumViewer;
using System.Drawing;
using System.Drawing.Imaging;
public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
var collected = new List<string>();
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.PDF_417
};
using var document = PdfDocument.Load(pdfPath);
for (int page = 0; page < document.PageCount; page++)
{
string temp = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png");
try
{
using var rendered = document.Render(page, 200, 200, PdfRenderFlags.CorrectFromDpi);
rendered.Save(temp, ImageFormat.Png);
using var bmp = new Bitmap(temp);
var decoded = reader.DecodeMultiple(bmp);
if (decoded != null)
collected.AddRange(decoded.Select(d => d.Text));
}
finally
{
if (File.Exists(temp))
File.Delete(temp);
}
}
return collected;
}
Imports ZXing
Imports ZXing.Windows.Compatibility
Imports PdfiumViewer
Imports System.Drawing
Imports System.Drawing.Imaging
Public Function ExtractBarcodesFromPdf(pdfPath As String) As List(Of String)
Dim collected As New List(Of String)()
Dim reader As New BarcodeReader()
reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.PDF_417
}
Using document = PdfDocument.Load(pdfPath)
For page As Integer = 0 To document.PageCount - 1
Dim temp As String = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png")
Try
Using rendered = document.Render(page, 200, 200, PdfRenderFlags.CorrectFromDpi)
rendered.Save(temp, ImageFormat.Png)
Using bmp As New Bitmap(temp)
Dim decoded = reader.DecodeMultiple(bmp)
If decoded IsNot Nothing Then
collected.AddRange(decoded.Select(Function(d) d.Text))
End If
End Using
End Using
Finally
If File.Exists(temp) Then
File.Delete(temp)
End If
End Try
Next
End Using
Return collected
End Function
IronBarcodeのアプローチ:
using IronBarCode;
public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
return BarcodeReader.Read(pdfPath)
.Select(r => r.Value)
.ToList();
}
using IronBarCode;
public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
return BarcodeReader.Read(pdfPath)
.Select(r => r.Value)
.ToList();
}
Imports IronBarCode
Public Function ExtractBarcodesFromPdf(pdfPath As String) As List(Of String)
Return BarcodeReader.Read(pdfPath) _
.Select(Function(r) r.Value) _
.ToList()
End Function
PdfiumViewerへの依存関係、ページレンダリングループ、DPI設定、一時ファイルの作成、およびクリーンアップブロックはすべて削除されました。 IronBarcodeはPDFファイルからバーコードをネイティブに読み取り、すべてのページを自動的に処理します。
バーコードの生成
ZXing.NetのライターはSystem.Drawing.Imagingを使って保存する必要があります。 IronBarcodeは組み込みの出力メソッドを持つGeneratedBarcodeを返します。
ZXing .NETアプローチ:
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using System.Drawing;
using System.Drawing.Imaging;
public void WriteCode128(string content, string outputPath)
{
var writer = new BarcodeWriter
{
Format = BarcodeFormat.CODE_128,
Options = new EncodingOptions
{
Width = 400,
Height = 120,
Margin = 10
}
};
using var bitmap = writer.Write(content);
bitmap.Save(outputPath, ImageFormat.Png);
}
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using System.Drawing;
using System.Drawing.Imaging;
public void WriteCode128(string content, string outputPath)
{
var writer = new BarcodeWriter
{
Format = BarcodeFormat.CODE_128,
Options = new EncodingOptions
{
Width = 400,
Height = 120,
Margin = 10
}
};
using var bitmap = writer.Write(content);
bitmap.Save(outputPath, ImageFormat.Png);
}
Imports ZXing
Imports ZXing.Common
Imports ZXing.Windows.Compatibility
Imports System.Drawing
Imports System.Drawing.Imaging
Public Sub WriteCode128(content As String, outputPath As String)
Dim writer = New BarcodeWriter With {
.Format = BarcodeFormat.CODE_128,
.Options = New EncodingOptions With {
.Width = 400,
.Height = 120,
.Margin = 10
}
}
Using bitmap = writer.Write(content)
bitmap.Save(outputPath, ImageFormat.Png)
End Using
End Sub
IronBarcodeのアプローチ:
using IronBarCode;
public void WriteCode128(string content, string outputPath)
{
BarcodeWriter.CreateBarcode(content, BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.SaveAsPng(outputPath);
}
using IronBarCode;
public void WriteCode128(string content, string outputPath)
{
BarcodeWriter.CreateBarcode(content, BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.SaveAsPng(outputPath);
}
Imports IronBarCode
Public Sub WriteCode128(content As String, outputPath As String)
BarcodeWriter.CreateBarcode(content, BarcodeEncoding.Code128) _
.ResizeTo(400, 120) _
.SaveAsPng(outputPath)
End Sub
ファイルに保存する代わりにバイナリ出力が必要な場合、返されるMemoryStreamの基本機能は必要ありません。
ZXing .NET API からIronBarcodeへのマッピング リファレンス
| ZXing.Net | IronBarcode | ノート |
|---|---|---|
new BarcodeReader() |
静的 - インスタンスなし | BarcodeReader.Read(...)は静的な呼び出しです |
reader.Options.PossibleFormats = new List<BarcodeFormat> { ... } |
不要 | 自動検出機能は50種類以上のフォーマットに対応しています。 |
reader.Options.TryHarder = true |
Speed = ReadingSpeed.Balanced |
精度の調整はBarcodeReaderOptionsで行います |
reader.Decode(bitmap) |
BarcodeReader.Read(imagePath).FirstOrDefault() |
ファイルパスを渡す — Bitmapの構築は必要ありません |
reader.DecodeMultiple(bitmap) |
BarcodeReader.Read(imagePath) |
常にコレクションを返します。 never null |
result.Text |
result.Value |
物件名が変更されました |
result.BarcodeFormat |
result.Format |
物件名が変更されました |
BarcodeFormat.QR_CODE |
BarcodeEncoding.QRCode |
列挙型の命名規則の変更 |
BarcodeFormat.CODE_128 |
BarcodeEncoding.Code128 |
列挙型の命名規則の変更 |
BarcodeFormat.EAN_13 |
BarcodeEncoding.EAN13 |
列挙型の命名規則の変更 |
BarcodeFormat.DATA_MATRIX |
BarcodeEncoding.DataMatrix |
列挙型の命名規則の変更 |
BarcodeFormat.PDF_417 |
BarcodeEncoding.PDF417 |
列挙型の命名規則の変更 |
new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... }} |
BarcodeWriter.CreateBarcode(data, encoding) |
静的ファクトリ、オプションなしオブジェクト |
Bitmapを返します |
.SaveAsPng(path) / .ToPngBinaryData() |
GeneratedBarcodeに組み込みの出力があります |
EncodingOptions { Width, Height } |
.ResizeTo(width, height) |
フルエントサイズ測定法 |
| PDFはサポートされていません | BarcodeReader.Read("file.pdf") |
ネイティブPDFサポート、全ページ |
一般的な移行の問題と解決策
第1号:バーコードリーダーのインスタンス化パターン
ZXing.Net: 呼び出し側はresult.Textを読み取ります。
解決策:インスタンス化を完全に削除する。 完全なパターンを静的呼び出しに置き換えます。
// Before: reader creation + format config + bitmap + decode + result.Text
// After:
var result = BarcodeReader.Read(imagePath).FirstOrDefault();
var value = result?.Value ?? string.Empty;
// Before: reader creation + format config + bitmap + decode + result.Text
// After:
var result = BarcodeReader.Read(imagePath).FirstOrDefault();
var value = result?.Value ?? string.Empty;
' Before: reader creation + format config + bitmap + decode + result.Text
' After:
Dim result = BarcodeReader.Read(imagePath).FirstOrDefault()
Dim value = If(result?.Value, String.Empty)
new BarcodeReader()をコードベースで検索し、すべてのインスタンスを見つけます。 それぞれが削除されるだけで、リファクタリングは行われません。
問題2:PossibleFormatsブロックの削除
ZXing .NET:すべてのデコード呼び出しの前に reader.Options.PossibleFormats = new List が続きます
解決策: 各PossibleFormats割り当てブロックを完全に削除します。 IronBarcodeはフォーマットの自動検出を実行します。 フォーマットリストは受け付けられませんし、必要もありません。 フォーマットリストに加えてSpeed = ReadingSpeed.Balancedを設定し、精度を調整します。
問題3:バインディングパッケージのクリーンアップ
ZXing.Net: System.Drawing.Bitmapを入力タイプとして参照しています。 SixLabors.ImageSharp.Image<Rgba32>を参照します。 どちらのパターンも、バインディングパッケージを削除すると機能しなくなります。
解決策:両方のバインディングパッケージを削除し、すべての画像読み込みコードを置き換えてください。 IronBarcodeのImage<t>の構築は必要ありません。 もっぱらusing System.Drawing;インポートも削除できます。
問題4:result.Textからresult.Valueへの変換
ZXing.Net: デコードされたバーコード値はresult.Textを介してアクセスされます。 バーコード形式はresult.BarcodeFormatを介してアクセスされます。
解決策: コードベース全体でresult.Formatに置き換えます。 どちらの変更も動作の違いがない単純なプロパティ名の変更です。
ZXing .NET移行チェックリスト
マイグレーション前のタスク
変更を加える前に、コードベースを監査して、ZXing for .NET参照をすべて見つけてください。
grep -r "using ZXing" --include="*.cs" .
grep -r "new BarcodeReader" --include="*.cs" .
grep -r "PossibleFormats" --include="*.cs" .
grep -r "BarcodeFormat\." --include="*.cs" .
grep -r "reader\.Decode\|reader\.DecodeMultiple" --include="*.cs" .
grep -r "result\.Text\|result\.BarcodeFormat" --include="*.cs" .
grep -r "new BarcodeWriter\|writer\.Write\|EncodingOptions" --include="*.cs" .
grep -r "PdfiumViewer\|PdfDocument\.Load" --include="*.cs" .
grep -r "using System\.Drawing" --include="*.cs" .
grep -r "using ZXing" --include="*.cs" .
grep -r "new BarcodeReader" --include="*.cs" .
grep -r "PossibleFormats" --include="*.cs" .
grep -r "BarcodeFormat\." --include="*.cs" .
grep -r "reader\.Decode\|reader\.DecodeMultiple" --include="*.cs" .
grep -r "result\.Text\|result\.BarcodeFormat" --include="*.cs" .
grep -r "new BarcodeWriter\|writer\.Write\|EncodingOptions" --include="*.cs" .
grep -r "PdfiumViewer\|PdfDocument\.Load" --include="*.cs" .
grep -r "using System\.Drawing" --include="*.cs" .
どのファイルがZXingバインディングパッケージ(Windows対ImageSharp)を参照しているかを文書化し、System.Drawing.BitmapがZXing入力のためにのみ使用されている場所を記録します。 Dockerfile(存在する場合)を確認してlibgdiplusのインストールを確認します。
コード更新タスク
PdfiumViewerNuGetパッケージを削除しますIronBarcodeNuGetパッケージをインストールします- アプリケーションのスタートアップに
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";を追加します - すべての
using IronBarCode;に置き換えます - すべての
new BarcodeReader()のインスタンス化を削除します - すべての
reader.Options.PossibleFormats = ...のブロックを削除します BarcodeReader.Read(imagePath).FirstOrDefault()に置き換えますBarcodeReader.Read(imagePath)に置き換えますresult.Valueに置き換えますresult.Formatに置き換えますBarcodeEncoding.Xの同等のもに更新します 12.new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... を置き換えます }}withBarcodeWriter.CreateBarcode(data, encoding).ResizeTo(w, h)writer.Write(data)+.ToPngBinaryData()に置き換えます- ZXing.Netのビットマップ読み込みのためだけに存在していたすべての
using System.Drawing;インポートを削除します - PDFの回避策として実装されていたPdfiumViewerのページレンダリングループをすべて削除します。
- Linux上で
libgdiplusを削除します
移行後のテスト
アプリケーションが以前に検出するように設定されていたすべてのバーコード形式が正常に検出されたことを確認します。
以前はPossibleFormatsリストから除外されていたバーコード形式を含む画像でテストし、自動検出がそれらを正しくピックアップすることを確認します。
- 負荷をかけた状態で並行処理パスを実行し、競合状態やnull結果がないことを確認します。
アプリケーションが PdfiumViewer を介して PDF を処理した場合は、同じ PDF 入力を提供し、バーコードの値が一致することを確認してください。
生成されたバーコード(Code 128、QRコードなど)が正しい出力形式と寸法であることを確認してください。
LinuxまたはDockerデプロイメントで、
libgdiplusを使用せずに画像の読み取りとPDFの読み取りが機能することを確認します。 - 全てのテストSuiteを実行し、出力を移行前のベースラインと比較する
IronBarcodeへの移行の主なメリット
スレッドセーフティの負担を排除: IronBarcodeの静的APIは、スレッドごとのインスタンスパターンを完全に排除します。 インスタンス化するリーダーもなく、スレッドごとにフォーマットリストを設定する必要もなく、ThreadLocalプールを管理する必要もありません。 同じ呼び出しは、シングルスレッド環境と高並行環境の両方で正しく動作し、並行処理の正しさは、呼び出し元ごとに委ねられるのではなく、ライブラリによって提供されます。
自動フォーマット検出: PossibleFormatsリストを削除することで、開発中に予期されていなかったバーコード形式を含むドキュメントで発生するサイレントミスの失敗カテゴリーが排除されます。 外部パートナーからの文書を処理するアプリケーションや、進化し続けるバーコード規格に対応するアプリケーションは、信頼性を維持するためにフォーマットリストのメンテナンスを必要としなくなりました。
ネイティブPDF処理: PdfiumViewerのレンダリングループ(ページ列挙、DPI設定、一時ファイルのライフサイクル、クリーンアップコードなど)は完全に削除されます。 以前はPDFバーコードを処理するために2つのライブラリ(ZXing .NETとPDFレンダラー)が必要だったアプリケーションが、今では1つのライブラリで処理できるようになりました。 デプロイされる依存関係が減少することで、ビルドとデプロイの両方のプロセスが簡素化されます。
単一のクロスプラットフォームパッケージ: WindowsとLinuxの展開におけるバインディングパッケージの区別がなくなります。 同じBarcodeReader.Read(path)呼び出しは、すべてのターゲットプラットフォームで同一にコンパイルされ、動作するため、画像読み込みコードのプラットフォーム条件を排除し、クロスプラットフォームの開発とコンテナ化のワークフローを簡素化します。
インフラストラクチャ コードの削減:この移行の最も重要な成果は、ZXing .NET統合に存在していた周辺インフラストラクチャ (ビットマップ読み込みブロック、フォーマット リスト、PdfiumViewer レンダリング ループ、ThreadLocal プール) が削除されたことです。これらはバーコード処理のためではなく、ライブラリのアーキテクチャ要件を満たすために存在していました。 移行後に残るのは、バーコードのロジックそのものです。 検出率やスキャンシナリオに関するより詳細な情報については、 ZXing .NETとIronBarcodeスキャナーの比較記事でより包括的な分析が提供されています。
よくある質問
なぜZXing.NETからIronBarcodeに移行する必要があるのですか?
一般的な理由としては、ライセンスの簡素化(SDK + ランタイムキーの複雑さの排除)、スループット制限の排除、ネイティブPDFサポートの獲得、Docker/CI/CDデプロイの改善、プロダクションコード内のAPI定型文の削減などが挙げられます。
ZXing.NETのAPIコールをIronBarcodeに置き換えるには?
インスタンスの作成とライセンスの定型文をIronBarCode.License.LicenseKey = "key "に置き換えてください。リーダー・コールをBarcodeReader.Read(path)に、ライター・コールをBarcodeWriter.CreateBarcode(data, encoding)に置き換えてください。静的メソッドはインスタンス管理を必要としません。
ZXing.NETからIronBarcodeに移行する際、コードはどのくらい変更されますか?
ほとんどのマイグレーションでは、コード行数は少なくなります。ライセンスの定型文、インスタンス・コンストラクタ、明示的なフォーマット設定が削除されます。コアとなる読み取り/書き込み操作は、より短いIronBarcodeに対応し、よりきれいな結果オブジェクトが得られます。
移行時にZXing.NETとIronBarcodeの両方をインストールしておく必要がありますか?
ほとんどのマイグレーションは、並列操作ではなく、直接置き換えです。一度に1つのサービスクラスを移行し、NuGet参照を置き換え、インスタンス化とAPI呼び出しパターンを更新してから次のクラスに移行します。
IronBarcodeのNuGetパッケージ名は何ですか?
パッケージは'IronBarcode'(大文字のBとC)です。Install-Package IronBarcode'または'dotnet add package IronBarcode'でインストールしてください。コード中のusingディレクティブは'using IronBarcode;'である。
IronBarcodeはZXing.Netと比較して、どのようにDockerデプロイを簡素化しますか?
IronBarcodeは外部SDKファイルやマウントされたライセンス設定のないNuGetパッケージです。Dockerでは、IRONBARCODE_LICENSE_KEY環境変数を設定すると、パッケージが起動時にライセンス検証を処理します。
IronBarcodeはZXing.Netから移行した後、すべてのバーコードフォーマットを自動的に検出しますか?
IronBarcodeは、サポートされているすべてのフォーマットのシンボルを自動検出します。明示的なBarcodeTypesの列挙は必要ありません。フォーマットが既に知られていて、パフォーマンスが重要な場合、BarcodeReaderOptionsは最適化として検索空間を制限することができます。
IronBarcodeは別のライブラリなしでPDFからバーコードを読み取ることができますか?
BarcodeReader.Read("document.pdf")は、PDFファイルをネイティブに処理します。結果には、見つかった各バーコードの PageNumber、Format、Value、および Confidence が含まれます。外部のPDFレンダリングステップは必要ありません。
IronBarcodeはどのようにパラレルバーコード処理を行うのですか?
IronBarcodeの静的メソッドはステートレスでスレッドセーフです。Parallel.ForEachをスレッドごとのインスタンス管理なしにファイルリスト上で直接使用します。BarcodeReaderOptions.MaxParallelThreadsは内部のスレッドバジェットを制御します。
ZXing.NETからIronBarcodeに移行した場合、どのような結果プロパティが変更されますか?
一般的なリネーム:BarcodeValueはValueに、BarcodeTypeはFormatに。IronBarcodeの結果にはConfidenceとPageNumberも追加されます。ソリューション全体の検索と置換は、既存の結果処理コードで名前の変更を処理します。
CI/CDパイプラインでIronBarcodeのライセンスを設定するには?
IRONBARCODE_LICENSE_KEYをパイプラインシークレットとして保存し、アプリケーションの起動コードにIronBarCode.License.LicenseKeyを割り当てます。1つのシークレットで、開発環境、テスト環境、ステージング環境、本番環境を含むすべての環境をカバーできます。
IronBarcodeはカスタムスタイルのQRコード生成に対応していますか?
はい。QRCodeWriter.CreateQrCode()は、ChangeBarCodeColor()によるカスタムカラー、AddBrandLogo()によるロゴ埋め込み、設定可能なエラー訂正レベル、PNG、JPG、PDF、ストリームなどの複数の出力形式をサポートしています。

