如何使用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
相关产品推荐
相关产品推荐

