Jak weryfikować sumy kontrolne kodów QR i stosować odporność na błędy w języku C

This article was translated from English: Does it need improvement?
Translated
View the article in English

Potoki kodów QR, które przetwarzają dane wejściowe z rzeczywistego świata, w tym wydrukowane etykiety, zdjęcia z aparatu lub zeskanowane dokumenty, napotkają symbole, które są zbyt uszkodzone, aby je zdekodować, oraz wyniki, które przejdą kontrolę sumy kontrolnej, ale nie przejdą walidacji biznesowej.

Korekcja błędów Reed-Solomona automatycznie eliminuje fizyczne uszkodzenia podczas dekodowania. Jeśli nie można odzyskać symbolu, zbiór wyników jest pusty, a nie częściowy. Walidacja na poziomie aplikacji jest oddzielna i polega na sprawdzeniu, czy zdekodowana wartość nie jest pusta, czy odpowiada oczekiwanemu formatowi lub czy zawiera prawidłowy adres URI przed dalszym przetwarzaniem.

W niniejszym poradniku wyjaśniono, jak weryfikować sumy kontrolne kodów QR i stosować kontrole odporności na błędy za pomocą biblioteki IronQR.

Szybki start: Sprawdzanie sum kontrolnych kodów QR

Odczytaj kod QR i sprawdź, czy dekodowanie się powiodło: wynik niepusty oznacza, że suma kontrolna Reeda-Solomona została zaliczona.

  1. Install IronQR with NuGet Package Manager

    PM > Install-Package IronQR
  2. Skopiuj i uruchom ten fragment kodu.

    using IronQr;
    using IronSoftware.Drawing;
    
    var reader = new QrReader();
    IEnumerable<QrResult> results = reader.Read(new QrImageInput("label.png"));
    
    if (!results.Any())
    {
        Console.WriteLine("No QR code detected or decoding failed.");
        return;
    }
    
    Console.WriteLine(results.First().Value);
  3. Wdrożenie do testowania w środowisku produkcyjnym

    Rozpocznij używanie IronQR w swoim projekcie już dziś z darmową wersją próbną

    arrow pointer

Weryfikacja sum kontrolnych kodów QR

Kody QR wykorzystują korekcję błędów Reeda-Solomona do wykrywania i naprawy uszkodzeń zakodowanych danych. Poziom korekty (niski – 7%, średni – 15%, kwartylowy – 25% lub wysoki – 30%) określa procent kodów, które mogą zostać utracone i nadal być odzyskane.

Jeśli chodzi o odczyt, podczas dekodowania wewnętrznie przeprowadzana jest weryfikacja sumy kontrolnej. Klasa QrResult nie udostępnia właściwości confidence; jeśli wynik istnieje w zbiorze, przekazana suma kontrolna. Jeśli dekodowanie nie powiedzie się, kolekcja jest pusta.

Dane wejściowe

Etykieta produktu z kodem QR kodująca https://ironsoftware.com/, generowana z korekcją błędów na poziomie Medium, reprezentująca etykietę, która mogła być przetworzona lub lekko porysowana podczas transportu.

Kodowanie kodu QR https://ironsoftware.com wykorzystywane jako dane wejściowe do weryfikacji sumy kontrolnej
:path=/static-assets/qr/content-code-examples/how-to/checksum-and-fault-tolerance/checksum-validation.cs
using IronQr;
using IronSoftware.Drawing;

var reader = new QrReader();
IEnumerable<QrResult> results = reader.Read(new QrImageInput("damaged-label.png"));

// Reed-Solomon decoding is pass/fail — presence in results means valid checksum
if (!results.Any())
{
    // Decoding failed entirely — damage exceeded the error correction capacity
    Console.WriteLine("QR code could not be decoded. Consider re-scanning or using a higher error correction level at generation time.");
    return;
}

foreach (QrResult result in results)
{
    // Decoded successfully — validate the content matches expected format
    if (string.IsNullOrWhiteSpace(result.Value))
    {
        Console.WriteLine("QR decoded but produced an empty value.");
        continue;
    }

    Console.WriteLine($"Valid QR: {result.Value}");
}
Imports IronQr
Imports IronSoftware.Drawing

Dim reader As New QrReader()
Dim results As IEnumerable(Of QrResult) = reader.Read(New QrImageInput("damaged-label.png"))

' Reed-Solomon decoding is pass/fail — presence in results means valid checksum
If Not results.Any() Then
    ' Decoding failed entirely — damage exceeded the error correction capacity
    Console.WriteLine("QR code could not be decoded. Consider re-scanning or using a higher error correction level at generation time.")
    Return
End If

For Each result As QrResult In results
    ' Decoded successfully — validate the content matches expected format
    If String.IsNullOrWhiteSpace(result.Value) Then
        Console.WriteLine("QR decoded but produced an empty value.")
        Continue For
    End If

    Console.WriteLine($"Valid QR: {result.Value}")
Next
$vbLabelText   $csharpLabel

Wynik

Konsola pokazuje zdekodowaną wartość https://ironsoftware.com/, potwierdzając, że dekodowanie Reed-Solomon zakończyło się sukcesem i ładunek został odzyskany w całości.

Wynik działania terminala pokazujący zdekodowany kod QR: https://ironsoftware.com

Aby zapewnić większą odporność na uszkodzenia fizyczne, generuj kody QR o wyższym poziomie korekcji błędów. Poziom High odzyskuje do 30% utraconych danych kosztem większego symbolu.


Obsługa rozpoznawania formatów podczas odczytu kodów QR

IronQR obsługuje trzy formaty kodowania QR: standardowy QR, Micro QR oraz prostokątny Micro QR. Skaner automatycznie wykrywa format podczas odczytu. Po zeskanowaniu pole QrResult.QrType dostarcza wykryty format jako wartość wyliczeniową.

Dla PDF-ów użyj QrPdfInput zamiast QrImageInput. Tryb skanowania określa równowagę między szybkością a dokładnością: Auto łączy wykrywanie przy użyciu uczenia maszynowego z klasycznym skanem, OnlyDetectionModel wykorzystuje tylko model ML dla szybszego przetwarzania, a OnlyBasicScan pomija zupełnie ML dla wysokiej jakości wstępnie przetworzonych obrazów.

Dane wejściowe

Etykieta produktu w formacie PNG (po lewej) i zdjęcie w formacie JPEG (po prawej), pokazujące odczyt z uwzględnieniem formatu w przypadku dwóch popularnych typów danych wejściowych.

product-label.png QR code used as input for format-aware reading
camera-capture.jpg JPEG QR code simulating a camera capture
:path=/static-assets/qr/content-code-examples/how-to/checksum-and-fault-tolerance/format-awareness.cs
using IronQr;
using IronSoftware.Drawing;
using IronQr.Enum;

// Read from an image file with ML + classic scan (default)
var reader = new QrReader();
IEnumerable<QrResult> results = reader.Read(new QrImageInput("product-label.png"));

foreach (QrResult result in results)
{
    // Inspect the detected QR format
    Console.WriteLine($"Format: {result.QrType}");   // QRCode, MicroQRCode, or RMQRCode
    Console.WriteLine($"Value:  {result.Value}");

    // Url is non-null only if Value is a valid URI
    if (result.Url != null)
    {
        Console.WriteLine($"URI:    {result.Url.AbsoluteUri}");
    }

    // Corner coordinates for positional context
    Console.WriteLine($"Corners: {result.Points.Length} points detected");
}

// Read from a bitmap with ML-only mode for faster throughput
var bitmap = AnyBitmap.FromFile("camera-capture.jpg");
var fastResults = reader.Read(new QrImageInput(bitmap, QrScanMode.OnlyDetectionModel));
Imports IronQr
Imports IronSoftware.Drawing
Imports IronQr.Enum

' Read from an image file with ML + classic scan (default)
Dim reader As New QrReader()
Dim results As IEnumerable(Of QrResult) = reader.Read(New QrImageInput("product-label.png"))

For Each result As QrResult In results
    ' Inspect the detected QR format
    Console.WriteLine($"Format: {result.QrType}")   ' QRCode, MicroQRCode, or RMQRCode
    Console.WriteLine($"Value:  {result.Value}")

    ' Url is non-null only if Value is a valid URI
    If result.Url IsNot Nothing Then
        Console.WriteLine($"URI:    {result.Url.AbsoluteUri}")
    End If

    ' Corner coordinates for positional context
    Console.WriteLine($"Corners: {result.Points.Length} points detected")
Next

' Read from a bitmap with ML-only mode for faster throughput
Dim bitmap As AnyBitmap = AnyBitmap.FromFile("camera-capture.jpg")
Dim fastResults = reader.Read(New QrImageInput(bitmap, QrScanMode.OnlyDetectionModel))
$vbLabelText   $csharpLabel

Wynik

Konsola wyświetla wykryty format, zdekodowaną wartość, rozpoznany adres URI oraz liczbę narożników dla etykiety produktu, a następnie liczbę wyników szybkiego skanowania dla obrazu z kamery.

Wynik wyświetlany w terminalu: Format: QRCode, Wartość: https://ironsoftware.com/product, URI oraz Narożniki: wykryto 4 punkty

Pole QrType jest przydatne, gdy aplikacja wymaga określonego formatu. Na przykład system magazynowy, który generuje wyłącznie standardowe kody QR, może odfiltrować nieoczekiwane wykrycia kodów Micro QR lub Rectangular Micro QR, które mogą wskazywać na zakłócenia lub niepowiązane etykiety. Każdy format ma inne właściwości pojemnościowe: standardowy kod QR obsługuje do 7089 znaków numerycznych, Micro QR do 35, a Rectangular Micro QR zapewnia prostokątny format dla ograniczonej przestrzeni na etykiecie.


Stosowanie kontroli wartości null do wyników kodów QR

QrReader.Read zwraca pustą kolekcję, jeśli nie znaleziono kodów QR; nigdy nie zwraca null. Jednak poszczególne właściwości wyników nadal wymagają weryfikacji. Na przykład Value może być puste, a Url zwraca null, jeśli zdekodowany ciąg nie jest prawidłowym URI.

Solidny wzorzec walidacji sprawdza trzy aspekty: liczbę elementów w zbiorze, integralność wartości oraz poprawność typu lub adresu URI przed przekazaniem danych do innego systemu.

Dane wejściowe

Puste, białe zdjęcie bez kodu QR, przedstawiające stronę dokumentu w partii mieszanej, w której niektóre strony nie posiadają etykiet nadających się do odczytu maszynowego.

Puste białe zdjęcie bez kodu QR użyte jako dane wejściowe do demonstracji sprawdzania wartości null
:path=/static-assets/qr/content-code-examples/how-to/checksum-and-fault-tolerance/null-checking-validator.cs
using IronQr;
using IronSoftware.Drawing;
using System.Collections.Generic;
using System.Linq;

public static class QrValidator
{
    public static List<QrResult> GetValidResults(
        string imagePath,
        QrEncoding? expectedFormat = null)
    {
        var reader = new QrReader();
        IEnumerable<QrResult> results = reader.Read(new QrImageInput(imagePath));

        // Guard: no QR codes detected
        if (!results.Any())
            return new List<QrResult>();

        return results
            .Where(r => !string.IsNullOrWhiteSpace(r.Value))
            .Where(r => expectedFormat == null || r.QrType == expectedFormat)
            .ToList();
    }
}

// Usage — only accept standard QR codes with non-empty values
var validated = QrValidator.GetValidResults(
    "shipping-manifest.png",
    expectedFormat: QrEncoding.QRCode);

if (validated.Count == 0)
{
    Console.WriteLine("No valid QR codes found for processing.");
    return;
}

foreach (var qr in validated)
{
    // Safe for downstream: value is non-empty, format is verified
    SendToInventoryApi(qr.Value, qr.Url?.AbsoluteUri);
}
Imports IronQr
Imports IronSoftware.Drawing
Imports System.Collections.Generic
Imports System.Linq

Public Module QrValidator
    Public Function GetValidResults(
        imagePath As String,
        Optional expectedFormat As QrEncoding? = Nothing) As List(Of QrResult)

        Dim reader As New QrReader()
        Dim results As IEnumerable(Of QrResult) = reader.Read(New QrImageInput(imagePath))

        ' Guard: no QR codes detected
        If Not results.Any() Then
            Return New List(Of QrResult)()
        End If

        Return results _
            .Where(Function(r) Not String.IsNullOrWhiteSpace(r.Value)) _
            .Where(Function(r) expectedFormat Is Nothing OrElse r.QrType = expectedFormat) _
            .ToList()
    End Function
End Module

' Usage — only accept standard QR codes with non-empty values
Dim validated = QrValidator.GetValidResults(
    "shipping-manifest.png",
    expectedFormat:=QrEncoding.QRCode)

If validated.Count = 0 Then
    Console.WriteLine("No valid QR codes found for processing.")
    Return
End If

For Each qr In validated
    ' Safe for downstream: value is non-empty, format is verified
    SendToInventoryApi(qr.Value, qr.Url?.AbsoluteUri)
Next qr
$vbLabelText   $csharpLabel

Wynik

Konsola wyświetla odpowiedź walidatora o pustym wyniku: nie wykryto żadnych kodów QR, więc zbiór jest pusty i żadne dane nie przechodzą do dalszego przetwarzania.

Wynik wyświetlany w terminalu: Nie znaleziono żadnych prawidłowych kodów QR do przetworzenia.

Walidator zwraca pustą listę (nigdy null), eliminując potrzebę sprawdzania null w miejscu wywołania. Opcjonalny parametr expectedFormat działa jako brama formatu, dzięki czemu kod wywołujący otrzymuje tylko wyniki zgodne z oczekiwanym typem formatu. Właściwość Url wykorzystuje operator warunkowy null do bezpiecznego obsługi zarówno ładunków URI, jak i nie-URI.

W przypadku przepływów pracy asynchronicznych zastosuj te same wzorce walidacji do ReadAsync: oczekuj na wywołanie i zastosuj identyczne sprawdzanie wynikowej kolekcji.


Więcej informacji

Zapoznaj się z opcjami licencyjnymi, gdy będziesz gotowy do produkcji.

Kliknij tutaj, aby pobrać kompletny projekt aplikacji konsolowej ChecksumFaultToleranceTest.

Curtis Chau
Autor tekstów technicznych

Curtis Chau posiada tytuł licencjata z informatyki (Uniwersytet Carleton) i specjalizuje się w front-endowym rozwoju, z ekspertką w Node.js, TypeScript, JavaScript i React. Pasjonuje się tworzeniem intuicyjnych i estetycznie przyjemnych interfejsów użytkownika, Curtis cieszy się pracą z nowoczesnymi frameworkami i tworzeniem dobrze zorganizowanych, atrakcyjnych wizualnie podrę...

Czytaj więcej
Gotowy, aby rozpocząć?
Nuget Pliki do pobrania 63,676 | Wersja: 2026.4 just released
Still Scrolling Icon

Wciąż przewijasz?

Czy chcesz szybko dowodu? PM > Install-Package IronQR
uruchom próbkę obserwuj, jak Twój URL staje się kodem QR.