You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用cpp-ZXing生成可识别的含宽字符二维码?

中文二维码生成识别失败的问题与解决

问题描述

用C++结合ZXing库生成二维码时,普通ASCII字符生成的二维码可正常识别,但中文等宽字符生成的二维码无法被在线公共识别工具识别。尝试过直接传入带L前缀的宽字符常量、构建std::wstring传入两种方式,且开启了UTF-8编码设置,均无效,生成的二维码内容与输入信息不匹配。

原代码

#include "ReadBarcode.h"
#include <iostream>
#include <array>
#include <string>

#include "BitMatrix.h"
#include "BitMatrixIO.h"
#include "CharacterSet.h"
#include "MultiFormatWriter.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>

#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

using namespace ZXing;

int main(int argc, char * argv[]){

    int sizeHint = 100;
    auto format = BarcodeFormatFromString("QRCode");
    auto writer = MultiFormatWriter(format).setMargin(10);

    //writer.setEncoding(CharacterSet::UTF8);
    
    // this will work with char*
    BitMatrix matrix = writer.encode("ddd", sizeHint, sizeHint);
    
     /* with Chinese charaters, the QR Code will be generated, but it 
     cannot be recognized by online public QR scanner.
     I've tried serveral ways. */

     // attempt 1. directly replace the paramter with `const w_char*`
     // BitMatrix matrix = writer.encode(L"你好", sizeHint, sizeHint);

    // attempt 2. build a std::wstring
    // std::wstring word = L"你好";
   // BitMatrix matrix = writer.encode(word, sizeHint, sizeHint);
   
    auto bitmap = ToMatrix<uint8_t>(matrix);
    int success = stbi_write_png("C:\\Users\\chenz\\Desktop\\2.png", bitmap.width(), bitmap.height(), 1, bitmap.data(), 0);

    if (!success) {
            std::cerr << "Failed to write image: " << std::endl;
            return -1;
    }
    std::cout << "qrcode done " << std::endl;
    return 0;
}

问题原因

ZXing库的宽字符encode接口会将宽字符串按系统默认多字节编码(如Windows下为GBK)转换为字节流,而主流二维码识别工具默认采用UTF-8编码解析内容,两者编码格式不匹配,导致识别失败或内容错误。

解决方法

核心是将中文宽字符串转换为UTF-8编码的窄字符串,同时明确告诉ZXing库使用UTF-8编码生成二维码。

步骤1:实现宽字符串转UTF-8的函数

添加宽字符串转UTF-8的转换逻辑(依赖C++标准库的codecvt):

#include <codecvt>
#include <locale>

// 将std::wstring转换为UTF-8编码的std::string
std::string wstring_to_utf8(const std::wstring& wstr) {
    std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
    return converter.to_bytes(wstr);
}

步骤2:修改主函数代码

开启UTF-8编码设置,转换中文内容为UTF-8字符串后传入encode接口:

int main(int argc, char * argv[]){

    int sizeHint = 100;
    auto format = BarcodeFormatFromString("QRCode");
    // 开启UTF-8编码设置
    auto writer = MultiFormatWriter(format).setMargin(10).setEncoding(CharacterSet::UTF8);

    // 处理中文内容:转UTF-8编码
    std::wstring word = L"你好";
    std::string utf8_content = wstring_to_utf8(word);
    BitMatrix matrix = writer.encode(utf8_content, sizeHint, sizeHint);
   
    auto bitmap = ToMatrix<uint8_t>(matrix);
    int success = stbi_write_png("C:\\Users\\chenz\\Desktop\\2.png", bitmap.width(), bitmap.height(), 1, bitmap.data(), 0);

    if (!success) {
            std::cerr << "Failed to write image: " << std::endl;
            return -1;
    }
    std::cout << "qrcode done " << std::endl;
    return 0;
}

补充说明

  • 如果使用C++17及以上版本,std::wstring_convert已被标记为废弃,可改用第三方库如utf8cpp,或使用平台API(如Windows的WideCharToMultiByte)实现编码转换。
  • 确认生成二维码时,ZXing库的编码设置与转换后的字符串编码一致,避免编码冲突。

附问题中的失败二维码

第二次尝试生成的二维码图片

内容的提问来源于stack exchange,提问作者Arthur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 23:53:17