c++ - 在 Windows 中使用 boost::program_options 从命令行参数中读取 Unicode 字符
问题描述
我有几个从命令行参数读取文件路径的 Windows 应用程序。一切都完美无缺,除非传递带有非 ANSI 字符的路径。我期待这个,但不知道如何处理它。可能是一个入门级的问题,但这让我发疯。
我当前的代码如下所示:
int main(int argc, char* argv[]) {
namespace po = boost::program_options;
po::options_description po_desc("Allowed options");
po_desc.add_options()
("file", po::value<std::string>(), "path to file");
po::variables_map po_vm;
try {
po::store(po::parse_command_line(argc, argv, po_desc), po_vm);
po::notify(po_vm);
} catch (...) {
std::cout << po_desc << std::endl;
return false;
}
const std::string file_path = po_vm["file"].as<std::string>();
// ...
}
我发现如果我替换file_path
from std::string
to的类型,boost::filesystem::path
现在会读取一些路径。我不知道确切原因,但可以推断它必须与来自 Latin1 字符集的翻译有关。
例如,有以下文件:
malaga.txt
málaga.txt
mąlaga.txt
第一个总是正确读取,而第二个在使用时失败,std::string file_path
但不是boost::filesystem::path file_path
。第三个总是失败。
我尝试将主函数切换为参数类型int main(int argc, wchar_t* argv)
并使用std::wstring
它,但它与boost::program_options
解析器不兼容。
如何正确读取此类 Unicode 文件名?
解决方案
感谢大家提出意见,感谢他们,我设法解决了我的问题。
TL;博士
这里是固定代码:
int wmain(int argc, wchar_t* argv[]) { // <<<
namespace po = boost::program_options;
po::options_description po_desc("Allowed options");
po_desc.add_options()
("file", po::wvalue<std::wstring>(), "path to file") // <<<
("ansi", po::value<std::string>(), "an ANSI string")
;
po::variables_map po_vm;
try {
po::store(po::wcommand_line_parser(argc, argv) // <<<
.options(po_desc)
.run(),
po_vm);
po::notify(po_vm);
} catch (...) {
std::cout << po_desc << std::endl;
return false;
}
const boost::filesystem::path file_path = po_vm["file"].as<std::wstring>(); // <<<
// ...
}
解释
首先,切换到wmain
and wchar_t* argv
: 正如@erik-sun所提到的,有必要将入口点切换到支持 Unicode 的函数。重要提示:可以使用int main(int, wchar_t*)
(在某种意义上它会编译),但它不会接收具有正确编码的参数并且解析器将失败,你必须使用wmain
.
然后,@richard-critten提供的Unicode 支持链接对于理解编译错误非常有用:
boost::program_options::wvalue
当类型为宽字符时使用。内部实现使用字符串流:默认的仅适用于 8 位字符。- 用于
boost::program_options::wcommand_line_parser
接受wchar_t*
参数。不幸的是,此类没有一体化构造函数,您必须使用长格式来解析命令行。 - 最后,在需要时检索值
std::wstring
。
我已经扩展了代码片段以显示它仍然与std::string
输入兼容。
边注
QApplication
我的完整解决方案需要在某个时候实例化一个 Qt 。QApplication
构造函数与 wide-char 不兼容argv
。由于 Qt 部分不需要命令行交互(Boost 很久以前就处理了所有内容),因此可以重写它以接收假参数:
int fake_argc = 1;
char* fake_argv[] = {"AplicationName"};
QApplication a(fake_argc, fake_argv);
推荐阅读
- javascript - 如何使用 JavaScript 验证表单
- laravel - 此集合实例上不存在属性 [products]。(看法:
- c++ - const 临时类型的最佳实践
- java - PDF 的编码问题
- amazon-cloudwatch - 使用“aws cloudwatch get-metric-widget-image”从 aws CLI 获取“singleValue”图像
- android - 如何使用 a2dp 和 avrcp 蓝牙配置文件连接两个 android 设备?
- python - 将字符串转换为所需的 json 格式
- java - IBM Watson:未经授权
- python-3.x - 从熊猫数据框中除零以外的列表列中获取重复次数最多的值
- python - 将数据框中的对象(时间)类型列转换为日期时间