c++ - 因 Unicode Boost C++ codecvts而困扰

  显示原文与译文双语对照的内容
0 0

在C++中,我想使用Unicode动手做。 所以最后掉进兔子洞的Unicode之后,我正准备丧生的机率的混淆,头痛,语言环境。

但是在Boost我一个挺麻烦的尝试使用Unicode文件路径并尝试使用Boost Program Options库与Unicode输入。 我读任何我能找到区域设置有关的主题,codecvts,unicode编码和Boost 。

我现在尝试把事情的步骤是让一个codecvt采用UTF 8 字符串并将其转换为平台上编码( UTF 8 POSIX,utf 16 Windows上),我一直想逃避 wchar_t.

最接近的是想实现这个目的,我实际上越来越Boost .Locale,在输出中的UTF 32 UTF 8 中的字符串转换为字符串。

#include <string>
#include <boost/locale.hpp>
#include <locale>

int main(void)
{
  std::string data("Testing, 㤹");

  std::locale fromLoc = boost::locale::generator().generate("en_US.UTF-8");
  std::locale toLoc   = boost::locale::generator().generate("en_US.UTF-32");

  typedef std::codecvt<wchar_t, char, mbstate_t> cvtType;
  cvtType const* toCvt = &std::use_facet<cvtType>(toLoc);

  std::locale convLoc = std::locale(fromLoc, toCvt);

  std::cout.imbue(convLoc);
  std::cout << data << std::endl;

  // Output is unconverted -- what?

  return 0;
}

我想过要使用宽字符转换某些其他种类的工作,但我真的不知道我是怎么在。 我不知道这个时候适合这项工作的工具是什么。 帮助?

时间: 原作者:

0 0

好了,经过长时间的几个月我已经找到答案了,我想帮助人们未来

首先,codecvt事情做这件事的做法是错误的。 boost .Locale字符集之间的转换提供一个简单的方式在其boost::locale::conv命名空间。 下面是一个示例( 有其他人不基于区域设置) 。

#include <boost/locale.hpp>
namespace loc = boost::locale;

int main(void)
{
  loc::generator gen;
  std::locale blah = gen.generate("en_US.utf-32");

  std::string UTF8String = "Tésting!";
  // from_utf will also work with wide strings as it uses the character size
  // to detect the encoding.
  std::string converted = loc::conv::from_utf(UTF8String, blah);

  // Outputs a UTF-32 string.
  std::cout << converted << std::endl;

  return 0;
}

如你所见,如果替换" en_US .utf 32 " 与" " 中它将输出用户的区域设置。

但不知道如何做std::cout也好不到哪里去,但translate( ) 函数的Boost .Locale输出在用户的区域设置。

至于文件系统使用UTF 8 字符串跨平台,看来这是否可行,这是链接如何做

原作者:
0 0
  std::cout.imbue(convLoc);
  std::cout << data << std::endl;

但这并没有转换, 因为它使用 codecvt<char, char, mbstate_t>它是一个no op . 唯一的标准使用codecvt流中的文件流。 std::cout根本不需要执行任何转换。

要强制Boost .Filesystem为窄字符串解释为使用 UTF 8 在windows上,boost::filesystem::imbue与区域设置与UTF 8 ↔ UTF 16 codecvt方面。 boost .Locale是后者的实现。

原作者:
0 0

Boost文件系统iostream替换类可以很好地使用UTF 16当使用Visual C++ 。

但是,它们无法工作( 审美的支持任意文件名) 当使用Windows中G++至少截至Boost版本1 .47 。 有代码注释解释,从本质上说,Visual C++标准库提供非标准 wchar_t基于的构造函数Boost文件系统类利用,但G++不支持这些扩展。

解决方法是使用8 .3 短文件名以来,但这种解决方案有点脆与旧Windows版本用户可以关闭自动生成短文件名。


中的示例代码使用Boost文件系统Windows :
#include "CmdLineArgs.h"        // CmdLineArgs
#include "throwx.h"             // throwX, hopefully
#include "string_conversions.h" // ansiOrFillerFrom( wstring )

#include <boost/filesystem/fstream.hpp>     // boost::filesystem::ifstream
#include <iostream>             // std::cout, std::cerr, std::endl
#include <stdexcept>            // std::runtime_error, std::exception
#include <string>               // std::string
#include <stdlib.h>             // EXIT_SUCCESS, EXIT_FAILURE
using namespace std;
namespace bfs = boost::filesystem;

inline string ansi( wstring const& ws ) { return ansiWithFillersFrom( ws ); }

int main()
{
    try
    {
        CmdLineArgs const   args;
        wstring const       programPath     = args.at( 0 );

        hopefully( args.nArgs() == 2 )
            || throwX( "Usage: " + ansi( programPath ) + " FILENAME" );

        wstring const       filePath        = args.at( 1 );
        bfs::ifstream       stream( filePath );     // Nice Boost ifstream subclass.
        hopefully( !stream.fail() )
            || throwX( "Failed to open file '" + ansi( filePath ) + "'" );

        string line;
        while( getline( stream, line ) )
        {
            cout << line << endl;
        }
        hopefully( stream.eof() )
            || throwX( "Failed to list contents of file '" + ansi( filePath ) + "'" );

        return EXIT_SUCCESS;
    }
    catch( exception const& x )
    {
        cerr << "!" << x.what() << endl;
    }
    return EXIT_FAILURE;
}
原作者:
...