Altbilgi içeriğine atla
VIDEOLAR

C# | IronPDF'de Unicode ve Uluslararası Dil Barkodları Nasıl Yazılır?

ZXing.Net'ten IronBarcode'a Geçiş

Bu kılavuz, .NET barkod okuma ve üretme uygulamaları için ZXing.Net'den IronBarcode'ye tam geçişi kapsar. ZXing.Net'in çekirdek paketi ve bağlama paketlerinin kaldırılmasına, mevcut olan yerde PdfiumViewer geçici çözümlerinin ortadan kaldırılmasına ve her durumsal BarcodeReader örneklemesinin IronBarcode'ın statik API'si ile değiştirilmesine değinmektedir. Her bölüm, genellikle ZXing.Net entegrasyonlarında uygulanan desenlerden alınmış öncesi ve sonrası kod içerir.

Neden ZXing.Net'ten Geçiş Yapılmalı

ZXing.Net, on yılı aşkın bir süredir .NET topluluğuna ücretsiz, Apache 2.0 barkod kütüphanesi olarak iyi hizmet vermiştir. Ancak, birkaç mimari kısıtlama, uygulamalar ölçek veya karmaşıklık olarak büyüdükçe operasyonel maliyetler haline gelir.

Thread Safety Sahipliği: ZXing.Net'in BarcodeReader bir durumsal objedir. Kütüphanenin kendi belgeleri, örneklerin iş parçacıkları arasında paylaşılmaması gerektiğini belirtir. Pratikte bu, her bir eşzamanlı işleme yolunun — eşzamanlı istekleri yönetmekte olan her denetleyici eylemin, paralel bir grupta yer alan her görevin — kendi okuyucusunu ayırması, yapılandırması ve atması gerektiği anlamına gelir. İstek hacmi arttıkça, bu ayırma deseni ölçülebilir bellek baskısı oluşturur. ThreadLocal<BarcodeReader> alternatifi tahsis sıklığını azaltır ancak kendi bertaraf karmaşıklığını beraberinde getirir. Her iki durumda da, eşzamanlılık altında doğruluk, kitaplığın sunduğu bir garanti değil, arayanın problemidir.

Biçim Belirtimi Riski: ZXing.Net, her çözme işlemi öncesinde reader.Options.PossibleFormats doldurulmasını gerektirir. Bu listedeki bir formatta olmayan bir barkod null döndürür — hiçbir istisna, uyarı, barkodun var ama tanınmıyor olduğuna dair bir belirti yoktur. Dış ortaklardan belgeler alan uygulamalar için, bu sessiz kaçırma davranışı bir güvenilirlik riskidir: bir yanlış gönderilen sipariş, kaçırılan hasta kayıt giriş kaydı veya hiç yazılmayan bir denetim kaydı, daha önceki bir gereksinim için yapılandırılmış ve asla güncellenmemiş bir format listesinden kaynaklanabilir.

PDF İşleme Boşluğu: ZXing.Net sadece bit eşlemlerini okur. Kaynak belgeler PDF ise — faturalar, nakliye manifestoları, uygunluk sertifikaları — arayanlar, ayrı bir PDF işleme kütüphanesi entegre etmeli (PdfiumViewer en yaygın), bir sayfa numaralama döngüsünü yerine getirmeli, DPI yapılandırmalı, geçici dosyaları yönetmeli ve başarı ve başarısızlık yollarının her ikisinde de temizleme işlemleriyle uğraşmalıdır. Bu, ZXing.Net'in okuyamadığı (PDF'leri) dönüştürmeye yarayan, sadece 30 ila 50 satırlık altyapı kodudur. Bu altyapının kendi bağımlılıkları, kendi dağıtım gereksinimleri ve kendi hata modları vardır.

Platform Bağlama Parçalanması: ZXing.Net'in görüntü yükleme yeteneği, platforma özgü bağlama paketleri arasında bölünmüştür. Windows bağlaması System.Drawing.Bitmap kullanır; platformlar arası bağlama farklı bir genel tür parametresi ve farklı bir using yönergesi ile SixLabors.ImageSharp kullanır. Windows'ta başlayıp daha sonra Linux üzerinde konteynerleştiren bir proje, hem NuGet referanslarını hem de imaj yüklü kodunu değiştirmek zorunda kalmalıdır. Aynı işlem için iki kod yolu, hata alanını genişletir ve tarama katmanında gelecekteki değişikliklere sürtüşme ekler.

Temel Sorun

ZXing.Net mimarisinin en açık bir göstergesi, bir tek iş parçacıklı çağrı ile eşzamanlı bir çağrı arasındaki farktır. ZXing.Net'te, eşzamanlı işleme, paralel operasyon başına tam bir okuyucu nesnesi oluşturulmasını gerektirir:

// 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)
$vbLabelText   $csharpLabel

IronBarcode bu nesneyi tamamen ortadan kaldırır. Statik çağrı, bir iş parçacığında veya yüz iş parçacığında çalıştırılsa da aynıdır:

// 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)
$vbLabelText   $csharpLabel

IronBarcode vs ZXing.Net: Özellik Karşılaştırması

Özellik ZXing.Net IronBarcode
Lisans Apache 2.0 (ücretsiz) Ticari
İş Parçacığı Güvenliği İş parçacığı güvenli değil — her iş parçacığı için yeni örnek gerekiyor İş parçacığı güvenli statik API
Format Algılama Manuel — PossibleFormats listesi gereklidir Otomatik — 50+ format
PDF Okuma Hayır — PdfiumViewer veya benzeri gerekiyor Yerel — tek bir yöntem çağrısı
Platform Desteği Her platform için ayrı bağlama paketleri Tek paket, tüm platformlar
Görsel Başına Birden Fazla Barkod Evet — DecodeMultiple Evet — varsayılan davranış
Barkod Üretimi Bitmap döner, manuel kaydetme gerektirir Yerleşik çıkışa sahip akıcı API
QR Kod Logo Desteği Hayır Evet
QR Kod Renk Kontrolü Hayır Evet
Hasarlı Barkod Kurtarma TryHarder bayrağı ML destekli görüntü düzeltme
Docker Ekstra Bağımlılıklar libgdiplus gerektirebilir None
Ticari SLA Desteği Hayır Evet
Gerekli NuGet Paketleri 2–3 (çekirdek + bağlama + isteğe bağlı ImageSharp) 1

Hızlı Başlangıç

Adım 1: ZXing.Net Paketlerini Kaldırın

Projeden tüm ZXing.Net ve ilgili paketlerini kaldırın:

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
SHELL

Yerel PdfiumViewer ikili dosyaları ayrı bir paket olarak yüklendiyse:

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

Dockerfile apt-get install -y libgdiplus içeriyorsa — Linux üzerinde Windows bağlaması üzerinden System.Drawing desteklemesi için eklenmişse — bu satır göç sonrası kaldırılabilir.

2. Adım: IronBarcode'u Kurun

dotnet add package IronBarcode
dotnet add package IronBarcode
SHELL

Ek bağlama paketleri veya platforma özgü bağımlılıklar gerekmemektedir. Aynı NuGet paketi, Windows, Linux, macOS ve Docker kapsayıcılarında çalışmaktadır. Dağıtım detayları için, IronBarcode Docker ve Linux kurulum kılavuzu, tam Dockerfile desenini kapsar.

Adım 3: Ad Alanlarını Güncelleyin ve Lisansı Başlatın

Barkod işlemleri kullanan her dosyadan tüm ZXing ilgili ad alanlarını çıkarın:

// 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
$vbLabelText   $csharpLabel

Herhangi bir barkod işlemi öncesinde, uygulama başlangıcında lisans başlatma ekleyin:

// 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"
$vbLabelText   $csharpLabel

Lisans anahtarı, bir ortam değişkeninden, appsettings.json üzerinden veya bir gizli yönetici aracılığıyla yüklenebilecek düz bir dizedir. Yerleştirilecek bir dosya yoktur ve yapılandırılacak bir yol yoktur.

Kod Göç Örnekleri

Görselden Tek Bir Barkod Okuma

Bu örnek, en yaygın ZXing.Net kullanım desenini değiştirir: bir okuyucuya başlamak, format listesini yapılandırmak, bir bit eşlemi yüklemek ve çözmek.

ZXing.Net Yaklaşımı:

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
$vbLabelText   $csharpLabel

IronBarcode Yaklaşımı:

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
$vbLabelText   $csharpLabel

Biçim listesi, Bitmap tahsisi ve using bloğu tamamen kaldırılmıştır. IronBarcode, bir dosya yolunu doğrudan kabul eder ve tüm desteklenen formatları otomatik olarak tespit eder. Önceden çözülen dizeyi döndüren özellik ZXing.Net'te result.Text idi; IronBarcode'da result.Value.

Görselden Tüm Barkodları Okuma

Bu örnek, ZXing.Net'te sessiz kaçırmaları önlemek için kapsamlı bir format listesi gerektiren DecodeMultiple yerine geçmektedir.

ZXing.Net Yaklaşımı:

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
$vbLabelText   $csharpLabel

IronBarcode Yaklaşımı:

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
$vbLabelText   $csharpLabel

BarcodeReader.Read her zaman bir koleksiyon döner ve asla null döndürmez, sonuç üzerinde null guard'u ortadan kaldırır. Hız ile doğruluk dengesini ayarlamak için, biçim kapsamını daraltmadan ReadingSpeed enumsını kapsayan okuma hız seçenekleri kılavuzuna bakınız.

Eşzamanlı Toplu İşleme

Bu örnek iş parçacığı güvenliği farkını en doğrudan şekilde gösterir. ZXing.Net, her paralel operasyon için yeni bir okuyucu gerektirir;IronBarcode eşzamanlılık seviyesi ne olursa olsun aynı statik çağrıyı kullanır.

ZXing.Net Yaklaşımı:

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
$vbLabelText   $csharpLabel

IronBarcode Yaklaşımı:

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
$vbLabelText   $csharpLabel

Korunacak veya izole edilecek bir okuyucu örneği yoktur. Asenkron boru hattı desenleri ve iş parçacığı sayısı yapılandırması için asenkron ve çok iş parçacıklı barkod okuma kılavuzunu inceleyin.

Bir PDF'den Barkod Çıkarma

Bu örnek PdfiumViewer render döngüsünü değiştirir. Var olan entegrasyon, PdfiumViewer yerine Ghostscript veya iText kullanıyorsa, önceki blok ayrıntılarda farklı görünecektir ama yapı olarak aynı olacaktır: ZXing.Net'e bit haritaları besleyen bir sayfa enum döngüsü.

ZXing.Net Yaklaşımı:

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
$vbLabelText   $csharpLabel

IronBarcode Yaklaşımı:

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
$vbLabelText   $csharpLabel

PdfiumViewer bağımlılığı, sayfa render döngüsü, DPI yapılandırması, geçici dosya oluşturma ve temizleme bloğu tamamen çıkarılır.IronBarcodePDF'lerden barkodları kendi başına okur, tüm sayfaları otomatik olarak işler.

Barkod Oluşturma

ZXing.Net yazarı, arayanların System.Drawing.Imaging kullanarak kaydetmesi gereken bir Bitmap döner. IronBarcode, yerleşik çıktı yöntemlerine sahip bir GeneratedBarcode döner.

ZXing.Net Yaklaşımı:

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
$vbLabelText   $csharpLabel

IronBarcode Yaklaşımı:

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
$vbLabelText   $csharpLabel

Dosyaya kaydetme yerine ikili çıktı gerekiyorsa, döndürülen GeneratedBarcode nesnesi üzerinde herhangi bir MemoryStream tesisat olmaksızın ToPngBinaryData() ve ToJpegBinaryData() mevcuttur.

ZXing.Net API'sinden IronBarcode'ye Harita Referansı

ZXing.Net IronBarcode Notlar
new BarcodeReader() Statik — örnek yok BarcodeReader.Read(...) statik bir çağrıdır
reader.Options.PossibleFormats = new List<BarcodeFormat> { ... } Gerekli değil Otomatik tespit, tüm 50+ formatı kapsar
reader.Options.TryHarder = true Speed = ReadingSpeed.Balanced BarcodeReaderOptions ile doğruluk ayarlama
reader.Decode(bitmap) BarcodeReader.Read(imagePath).FirstOrDefault() Dosya yolu geç — Bitmap inşasına gerek yok
reader.DecodeMultiple(bitmap) BarcodeReader.Read(imagePath) Her zaman bir koleksiyon döner; never null
result.Text result.Value Özellik yeniden adlandırıldı
result.BarcodeFormat result.Format Özellik yeniden adlandırıldı
BarcodeFormat.QR_CODE BarcodeEncoding.QRCode Enum adlandırma kuralı değişikliği
BarcodeFormat.CODE_128 BarcodeEncoding.Code128 Enum adlandırma kuralı değişikliği
BarcodeFormat.EAN_13 BarcodeEncoding.EAN13 Enum adlandırma kuralı değişikliği
BarcodeFormat.DATA_MATRIX BarcodeEncoding.DataMatrix Enum adlandırma kuralı değişikliği
BarcodeFormat.PDF_417 BarcodeEncoding.PDF417 Enum adlandırma kuralı değişikliği
new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... } } BarcodeWriter.CreateBarcode(data, encoding) Statik fabrika, seçenekler nesnesi yok
writer.Write(data) Bitmap döner .SaveAsPng(path) / .ToPngBinaryData() GeneratedBarcode üzerinde yerleşik çıktı
EncodingOptions { Width, Height } .ResizeTo(width, height) Akıcı boyutlandırma yöntemi
PDF desteği yok BarcodeReader.Read("file.pdf") Yerel PDF desteği, tüm sayfalar

Yaygın Göç Sorunları ve Çözümleri

Sorun 1: BarcodeReader Başlatma Desenleri

ZXing.Net: Aramalar bir new BarcodeReader() oluşturur, reader.Options.PossibleFormats ayarlar, bir Bitmap yükler, reader.Decode(bitmap) veya reader.DecodeMultiple(bitmap) çağırır ve result.Text okur.

Çözüm: Başlatmayı tamamen kaldırın. Tam deseni bir statik çağrı ile değiştirin:

// 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)
$vbLabelText   $csharpLabel

new BarcodeReader() kod tabanında arayın ve her bir örneği bulun. Her biri kaldırılır, yeniden düzenlenmez.

Sorun 2: PossibleFormats Bloğunun Kaldırılması

ZXing.Net: Her kod çözme çağrısı öncereader.Options.PossibleFormats = new List<BarcodeFormat> { ... }ataması. Bu listeler genellikle uzun ve projeye özeldir.

Çözüm: Her bir PossibleFormats atama bloğunu tamamen silin.IronBarcode otomatik format algılama yapar; hiçbir format listesi kabul edilmez veya gerekmez. TryHarder = true bayrağı, biçim listesiyle birlikte ayarlandıysa, doğruluk ayarlaması gerekiyorsa, onu BarcodeReaderOptions nesnesi üzerinde Speed = ReadingSpeed.Balanced ile değiştirin.

Sorun 3: Paket Temizliği Bağlama

ZXing.Net: ZXing.Net.Bindings.Windows.Compatibility kullanan projeler, giriş türü olarak System.Drawing.Bitmap referans alır. ZXing.Net.Bindings.ImageSharp kullanan projeler SixLabors.ImageSharp.Image<Rgba32> referans alır. Her iki desen de bağlama paketleri kaldırıldıktan sonra bozulur.

Çözüm: Her iki bağlama paketini de kaldırın ve tüm görüntü yükleme kodunu değiştirin. IronBarcode'ın BarcodeReader.Read bir dosya yolu dizesi, byte[], Stream veya Uri kabul eder — Bitmap veya Image<t> inşasına gerek yoktur. Sadece Bitmap yükleme için var olan kalan using System.Drawing; ithalatları da kaldırılabilir.

Sorun 4: result.Text to result.Value

ZXing.Net: Çözülen barkod değeri, result.Text aracılığıyla erişilir. Barkod formatına result.BarcodeFormat ile erişilir.

Çözüm: Kod tabanındaki result.Text yerine result.Value ve result.BarcodeFormat yerine result.Format kullanın. Her iki değişiklik de davranışsal bir fark olmaksızın basit birer özellik yeniden adlarıdır.

ZXing.Net Göç Kontrol Listesi

Geçiş Öncesi Görevler

ZXing.Net referanslarını aramaya başlamadan önce tüm kod tabanını inceleyin:

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" .
SHELL

Hangi dosyaların ZXing bağlama paketlerini (Windows'a karşı ImageSharp'a karşı) referans aldığını ve burada sadece ZXing girişi için System.Drawing.Bitmap kullanıldığını belgeleyin. Dockerfile'ı (mevcutsa) libgdiplus kurulumu için inceleyin.

Kod Güncelleme Görevleri

  1. ZXing.Net, ZXing.Net.Bindings.Windows.Compatibility, ZXing.Net.Bindings.ImageSharp ve PdfiumViewer NuGet paketlerini kaldırın
  2. IronBarcode NuGet paketini yükleyin
  3. Başvuru başlatma kısmına IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"; ekleyin
  4. Tüm using ZXing* ve using SixLabors.ImageSharp* ithalatlarını using IronBarCode; ile değiştirin
  5. Her new BarcodeReader() örneklemesini kaldırın
  6. Her reader.Options.PossibleFormats = ... bloğunu silin
  7. reader.Decode(bitmap) ile BarcodeReader.Read(imagePath).FirstOrDefault() değiştirin
  8. reader.DecodeMultiple(bitmap) ile BarcodeReader.Read(imagePath) değiştirin
  9. result.Text ile result.Value değiştirin
  10. result.BarcodeFormat ile result.Format değiştirin
  11. BarcodeFormat.X enum referanslarını eşdeğerleri ile güncelleyin 12.new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... } }with BarcodeWriter.CreateBarcode(data, encoding).ResizeTo(w, h)
  12. writer.Write(data) + bitmap.Save(...) ile .SaveAsPng(path) veya .ToPngBinaryData() değiştirin
  13. Yalnızca ZXing.Net bitmap yüklemesi için var olan tüm using System.Drawing; ithalatlarını kaldırın
  14. PdfiumViewer sayfa oluşturma döngüsünü bir PDF çözümü olarak nerede uygulanmışsa kaldırın
  15. Dockerfile'dan libgdiplus'i kaldırın eğer Linux'da System.Drawing desteklemek için eklenmişse

Geçiş Sonrası Testler

  • Uygulamanın daha önce algılamak üzere yapılandırıldığı tüm barkod formatlarının başarılı bir şekilde bulunduğunu doğrulayın
  • Daha önce PossibleFormats listesinde hariç tutulan barkod formatlarını içeren görsellerle test edin, otomatik algılamanın onları aldığını doğrulamak için
  • Yük altında eşzamanlı işleme yollarını çalıştırın ve hiçbir yarış durumu veya null sonuç olmadığını doğrulayın
  • Uygulama PdfiumViewer aracılığıyla PDF'leri işlerse, aynı PDF girişlerini sağlayın ve barkod değerlerinin eşleştiğini doğrulayın
  • Üretilen barkodların (Kod 128, QR Kodu vb.) doğru çıkış formatı ve boyutlarını ürettiğini teyit edin
  • Linux veya Docker dağıtımlarında, görsel okuma ve PDF okumanın libgdiplus olmadan çalıştığını doğrulayın
  • Tam test paketi çalıştırın ve çıktıyı göç öncesi referansla karşılaştırın

IronBarcode'a Geçmenin Temel Faydaları

Ortam Güvenliği Yükü Kaldırıldı: IronBarcode'un statik API'si, her bir konu örneği modelini tamamen kaldırır. Hiçbir okuyucu örneklemeye gerek yoktur, thread başına yapılandırılacak bir format listesi yoktur ve yönetilecek bir ThreadLocal havuzu yoktur. Aynı çağrı, hem tek konu hem de yüksek dereceli eşzamanlı ortamlarda doğrudur ve eşzamanlılık doğruluğu, her bir arayıcıya devredilmek yerine kütüphaneye sağlanır.

Otomatik Format Algılama: PossibleFormats listesinin kaldırılması, geliştirme sırasında belgelerde öngörülemeyen barkod formatları içerdiğinde gerçekleşen sessiz kaçırma hatalarını ortadan kaldırır. Dış ortaklardan gelen belgeleri işleyen veya gelişen barkod standartları üzerinde çalışan uygulamaların artık güvenilir kalmak için format listesi bakımı gerektirmemesi gerekmiyor.

Yerel PDF İşleme: PdfiumViewer oluşturma döngüsü — sayfa numaralandırması, DPI yapılandırması, geçici dosya yaşam döngüsü ve temizleme kodu — tamamen kaldırılır. Daha önce bir PDF barkodunu işlemek için iki kütüphane (ZXing.Net ve bir PDF oluşturucu) gerektiren uygulamalar artık bir kullanıyor. Distribü edilen bağımlılıkların azaltılması, hem derleme hem de dağıtım yüzeylerini basitleştirir.

Tek Çapraz Platform Paketi: Windows ve Linux dağıtımları arasındaki bağlama paket farkı ortadan kaldırılır. Aynı BarcodeReader.Read(path) çağrısı tüm hedef platformlarda aynı şekilde derlenir ve davranır, görsel yükleme kodunda platform şartlarını ortadan kaldırır ve platformlar arası geliştirme ve konteynerleştirme iş akışlarını basitleştirir.

Ana Yapı Kodunun Azaltılması: Göçün en önemli sonucu, çevredeki altyapının kaldırılmasıdır — Bitmap yükleme blokları, format listeleri, PdfiumViewer oluşturma döngüleri, ThreadLocal havuzları — ZXing.Net entegrasyonlarındaki kütüphanenin mimari gereksinimlerini karşılamak için var olan. Göçten sonra kalan tek şey barkod mantığının kendisidir. Tespit oranları ve tarama senaryoları hakkında daha fazla bağlam için, ZXing.Net vs IronBarcode tarayıcı karşılaştırması daha geniş bir analiz sağlar.

Lütfen dikkate alınGhostscript, PDFium, ZXing.NET ve iText, ilgili sahiplerinin tescilli ticari markalarıdır. Bu site Artifex Software, Chromium Project, Google, ZXing.NET veya iText Group tarafından yetkilendirilmiş, desteklenmemiş veya sponsorluk edilmemiştir. Tüm ürün adları, logolar ve markalar ilgili sahiplerinin mülkiyetindedir. Karşılaştırmalar, yalnızca bilgilendirme amaçlıdır ve yazı sırasında halka açık bilgilerle alakalı olarak yansıtılmaktadır.

Sıkça Sorulan Sorular

Neden ZXing.Net'den IronBarcode'a göç etmeliyim?

Yaygın nedenler arasında lisanslamanın basitleştirilmesi (SDK + runtime anahtar karmaşıklığının kaldırılması), veri geçiş limitlerinin ortadan kaldırılması, yerel PDF desteği kazanılması, Docker/CI/CD dağıtımının iyileştirilmesi ve üretim kodunda API tekrarlama azalması yer alır.

ZXing.Net API çağrılarını IronBarcode ile nasıl değiştirebilirim?

Örnek oluşturma ve lisanslama tekrarlamalarını IronBarCode.License.LicenseKey = "anahtar" ile değiştirin. Okuyucu çağrılarını BarcodeReader.Read(yol) ile ve yazıcı çağrılarını BarcodeWriter.CreateBarcode(veri, kodlama) ile değiştirin. Statik yöntemler örnek yönetimi gerektirmez.

ZXing.Net'den IronBarcode'a geçerken kodda ne kadar değişiklik oluyor?

Çoğu geçiş daha az kod satırıyla sonuçlanır. Lisanslama tekrarlamaları, örnek oluşturucular ve açık format yapılandırması kaldırılır. Temel okuma/yazma işlemleri, daha temiz sonuç nesneleriyle daha kısa IronBarcode eşdeğerlerine dönüştürülür.

Geçiş sırasında ZXing.Net ve IronBarcode'u bir arada tutmam gerekiyor mu?

Hayır. Çoğu geçiş doğrudan değişim yapılır, paralel bir işletim yerine geçer. Bir hizmet sınıfını bir seferde geçirin, NuGet referansını değiştirin ve sonraki sınıfa geçmeden önce başlatma ve API çağrı desenlerini güncelleyin.

IronBarcode için NuGet paketi adı nedir?

Paket 'IronBarCode' (büyük B ve C harfleriyle). 'Install-Package IronBarCode' veya 'dotnet add package IronBarCode' ile kurun. Kodda kullanılan yönerge 'using IronBarCode;' şeklindedir.

IronBarcode, Docker dağıtımını ZXing.Net'ye kıyasla nasıl kolaylaştırır?

IronBarcode, harici SDK dosyaları veya montajlı lisans yapılandırması olmayan bir NuGet paketidir. Docker'da, IRONBARCODE_LICENSE_KEY ortam değişkenini ayarlayın ve paket lisans doğrulamasını başlangıçta kendi kendine yapar.

ZXing.Net'den geçiş yaptıktan sonra IronBarcode tüm barkod formatlarını otomatik olarak algılar mı?

Evet. IronBarcode, desteklenen tüm formatlardaki sembolojiyi otomatik olarak algılar. Açık BarcodeTypes sayımı gerekli değildir. Format zaten biliniyorsa ve performans önemliyse, BarcodeReaderOptions arama alanını optimize etmek için sınırlamayı sağlar.

IronBarcode, ayrı bir kütüphane olmadan PDF'lerden barkod okuyabiliyor mu?

Evet. BarcodeReader.Read("document.pdf") PDF dosyalarını yerel olarak işlemler. Sonuçlar her barkod için SayfaNumarası, Format, Değer ve Güven içerir. Harici bir PDF render adımı gerekmez.

IronBarcode, paralel barkod işlemeyi nasıl yönetiyor?

IronBarcode'un statik yöntemleri durumsuz ve thread-safe'dir. Dağıtılmış dosya listeleri üzerinde per-thread örnek yönetimi olmadan doğrudan Parallel.ForEach kullanın. BarcodeReaderOptions.MaxParallelThreads, iç thread bütçesini kontrol eder.

ZXing.Net'den IronBarcode'a geçerken hangi sonuç özellikleri değişir?

Yaygın yeniden adlandırmalar: BarcodeValue, Value olur; BarcodeType, Format olur. IronBarcode sonuçları ayrıca Güven ve SayfaNumarası ekler. Çözüm çapında arama-değiştirme, mevcut sonuç işleme kodundaki yeniden adlandırmaları ele alır.

Bir CI/CD hattında IronBarcode lisanslamasını nasıl ayarlayabilirim?

IRONBARCODE_LICENSE_KEY'i bir boru hattı sırrı olarak saklayın ve uygulama başlangıç kodunda IronBarCode.License.LicenseKey olarak atayın. Bir sır, geliştirme, test, aşama ve üretim dahil olmak üzere tüm ortamları kapsar.

IronBarcode, özel biçimlendirmeye sahip QR kodu üretimini destekliyor mu?

Evet. QRCodeWriter.CreateQrCode() özelleştirilmiş renkler için ChangeBarCodeColor(), logo yerleştirme için AddBrandLogo(), yapılandırılabilir hata düzeltme seviyeleri ve PNG, JPG, PDF ve akış dahil birden çok çıktı formatını destekler.

Curtis Chau
Teknik Yazar

Curtis Chau, Bilgisayar Bilimleri alanında Lisans Derecesine (Carleton Üniversitesi) sahip ve Node.js, TypeScript, JavaScript ve React konularında uzmanlaşmış ön uç geliştirmeyle ilgileniyor. Sezgisel ve estetik açıdan hoş kullanıcı arayüzleri oluşturma tutkunu, Curtis modern çerçevelerle çalışmayı ve iyi yapı...

Daha Fazla Oku

Iron Destek Ekibi

Haftada 5 gün, 24 saat çevrimiçiyiz.
Sohbet
E-posta
Beni Ara