Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Unicode代码指向字节和反向:C++中如何实现?_Java_C++_C++11_Character Encoding - Fatal编程技术网

Java Unicode代码指向字节和反向:C++中如何实现?

Java Unicode代码指向字节和反向:C++中如何实现?,java,c++,c++11,character-encoding,Java,C++,C++11,Character Encoding,作为一个介绍,我使用Java,过去也使用过不少C语言 在Java中,字符串文字可以包含任何一组图形,只要您可以在编辑环境中输入它们;然后,所述编辑环境将以当时使用的任何字符编码保存源文件 在运行时,只要编译器支持编码,字节码将所有字符串文本表示为一组字符,其中一个字符表示一个UTF-16代码单元。因此,BMP之外的Unicode代码点需要两个字符;您可以使用获取表示BMP之外的Unicode代码点所需的字符数组 您有用于字符编码的类,将字符序列编码为字节序列的过程,以及相反的过程。因此,无论源/

作为一个介绍,我使用Java,过去也使用过不少C语言

在Java中,字符串文字可以包含任何一组图形,只要您可以在编辑环境中输入它们;然后,所述编辑环境将以当时使用的任何字符编码保存源文件

在运行时,只要编译器支持编码,字节码将所有字符串文本表示为一组字符,其中一个字符表示一个UTF-16代码单元。因此,BMP之外的Unicode代码点需要两个字符;您可以使用获取表示BMP之外的Unicode代码点所需的字符数组

您有用于字符编码的类,将字符序列编码为字节序列的过程,以及相反的过程。因此,无论源/目标使用何种字符编码,无论是文件、套接字还是其他,都可以根据需要进行编码/解码

现在,让我们假设C++11。介绍了std::u32string、std::u16string;据我所知,这些都是std::basic_string和std::basic_string的别名,它们的最终效果是,在运行时,使用u和u声明的字符串常量由16位或32位实体组成,分别表示UTF-16或UTF-32代码单元。还有一个u8,后者的基本字符串类型是什么(如果有的话),因为它没有固定的长度

其他要点:UTF-16有两种变体,LE和BE;java确实是,因为在字节码级别,一切都是。字符{16,32}是否依赖于代码中的endianness

但是,即使经过数小时的搜索,我也找不到答案:C++11作为标准,是否可以像标准JDK那样,将任何字符串常量转换为合适的字节序列,反之亦然,给定一个字符编码?我怀疑这会变得更加困难,因为在运行时,字符串文字基本上有三种表示形式,甚至不需要去char*,它基本上是一个字节数组


编辑:添加到相关javadoc的链接,您可以通过使用codevt locale方面进行转换

用法有些不直观,但我就是这么做的:

/** Convert utf8 stream to UCS-4 stream */
u32string decode(string utf8)
{
    std::wstring_convert<std::codecvt_utf8<char32_t>,char32_t> convert;
    return convert.from_bytes(utf8);
}

/** Convert UCS-4 stream to utf8 stream */
string encode(u32string ucs4)
{
    std::wstring_convert<std::codecvt_utf8<char32_t>,char32_t> convert;
    return convert.to_bytes(ucs4);
}

它需要一个像样的编译器,但对我来说,只有clang工作正常,gcc编译但生成的结果无效。新版本的gcc可能还可以。

您可以使用codevt locale方面进行转换

#include <string>
#include <codecvt>
#include <locale>

template<typename Facet>
struct usable_facet : Facet {
  using Facet::Facet;
  ~usable_facet() = default;
};

int main() {    
    using utf16_codecvt = usable_facet<std::codecvt<char16_t, char, std::mbstate_t>>;
    using utf32_codecvt = usable_facet<std::codecvt<char32_t, char, std::mbstate_t>>;

    std::wstring_convert<utf16_codecvt, char16_t> u16convert; // bidirectional UTF-16/UTF-8 conversion
    std::wstring_convert<utf32_codecvt, char32_t> u32convert; // bidirectional UTF-32/UTF-8 

    std::string utf8 = u16convert.to_bytes(u"UTF-16 data");
    std::u16string utf16 = u16convert.from_bytes(u8"UTF-8 data");

    utf8 = u32convert.to_bytes(U"UTF-32 data");
    std::u32string utf32 = u32convert.from_bytes(u8"UTF-8 data");
}
用法有些不直观,但我就是这么做的:

/** Convert utf8 stream to UCS-4 stream */
u32string decode(string utf8)
{
    std::wstring_convert<std::codecvt_utf8<char32_t>,char32_t> convert;
    return convert.from_bytes(utf8);
}

/** Convert UCS-4 stream to utf8 stream */
string encode(u32string ucs4)
{
    std::wstring_convert<std::codecvt_utf8<char32_t>,char32_t> convert;
    return convert.to_bytes(ucs4);
}
它需要一个像样的编译器,但对我来说,只有clang工作正常,gcc编译,但生成的结果无效,新版本的gcc可能还可以

#include <string>
#include <codecvt>
#include <locale>

template<typename Facet>
struct usable_facet : Facet {
  using Facet::Facet;
  ~usable_facet() = default;
};

int main() {    
    using utf16_codecvt = usable_facet<std::codecvt<char16_t, char, std::mbstate_t>>;
    using utf32_codecvt = usable_facet<std::codecvt<char32_t, char, std::mbstate_t>>;

    std::wstring_convert<utf16_codecvt, char16_t> u16convert; // bidirectional UTF-16/UTF-8 conversion
    std::wstring_convert<utf32_codecvt, char32_t> u32convert; // bidirectional UTF-32/UTF-8 

    std::string utf8 = u16convert.to_bytes(u"UTF-16 data");
    std::u16string utf16 = u16convert.from_bytes(u8"UTF-8 data");

    utf8 = u32convert.to_bytes(U"UTF-32 data");
    std::u32string utf32 = u32convert.from_bytes(u8"UTF-8 data");
}
在任意语言环境编码的文本和任何Unicode编码之间转换的唯一标准方法是c16rtomb和C32R之类的低级函数支持较差


在任意语言环境编码的文本和任何Unicode编码之间转换的唯一标准方法是低级别函数(如c16rtomb和C32RCOMB)的支持不足。

C++未指定源文件编码。事实上,它支持EBCDIC。所有C++11编译器都支持UTF-8,许多编译器通过传递适当的标志来支持其他编码

该标准为基本源字符集之外的字符指定了转义码语法,基本源字符集基本上由该语言使用的字符组成。基本源字符集之外的字符称为扩展字符,在编译或甚至预处理源代码之前,它们会被相应的代码替换。这确保了源代码的含义独立于其编码

char32和char16没有内置endianness。它们只是简单地等同于uint32和uint16。您可以说它们继承了本机的endianness,但直接将对象表示形式序列化为字节是一种滥用

要可靠地指定UTF-8文本,并覆盖任何相反的编译器设置,请使用准备好序列化的u8。u和u没有endianness,因为值已烘焙到程序中

要序列化,可以使用codevt_utf8和codevt_utf16类模板,它们采用编译时模板标志指定文件格式:

enum codecvt_mode {
    consume_header = 4,
    generate_header = 2,
    little_endian = 1
};
要在二进制模式下设置流文件,将char32_t字符串编码为带有字节顺序标记的UTF-16LE,您可以使用

std::basic_ofstream< char32_t > file( path, std::ios::binary );

file.imbue( std::locale( file.locale(), new std::codecvt_utf16<
        char32_t,
        std::codecvt_mode::generate_header | std::codecvt_mode::little_endian
     >{} ) );

这比输出前进行翻译更可取。

C++没有指定源文件编码。事实上,它支持EBCDIC。所有C++11编译器都支持UTF-8,许多编译器通过传递适当的标志来支持其他编码

该标准为基本源字符集之外的字符指定了转义码语法,基本源字符集基本上由该语言使用的字符组成。基本源字符集之外的字符称为扩展字符,在编译或甚至预处理源代码之前,它们会被相应的代码替换。这确保了 源代码的含义与编码无关

char32和char16没有内置endianness。它们只是简单地等同于uint32和uint16。您可以说它们继承了本机的endianness,但直接将对象表示形式序列化为字节是一种滥用

要可靠地指定UTF-8文本,并覆盖任何相反的编译器设置,请使用准备好序列化的u8。u和u没有endianness,因为值已烘焙到程序中

要序列化,可以使用codevt_utf8和codevt_utf16类模板,它们采用编译时模板标志指定文件格式:

enum codecvt_mode {
    consume_header = 4,
    generate_header = 2,
    little_endian = 1
};
要在二进制模式下设置流文件,将char32_t字符串编码为带有字节顺序标记的UTF-16LE,您可以使用

std::basic_ofstream< char32_t > file( path, std::ios::binary );

file.imbue( std::locale( file.locale(), new std::codecvt_utf16<
        char32_t,
        std::codecvt_mode::generate_header | std::codecvt_mode::little_endian
     >{} ) );

这比输出前进行翻译更可取。

可能会有所帮助。基本C++没有编码,你必须在更高的层次上处理自己。我确实认识其中的一些关键字,但如何在代码中实际使用它。。。另外,UTF-16 LE和UTF-16是如何比较的?@fge使用或查看BOM。@Cubbi这不是我真正的问题;假设我在LE或BE平台上使用u;我保证结果一致吗?@lge如果您将u文本重新解释为char*,您将得到LE,或者取决于刚刚在IBM和x86上测试的平台,以确保可能会有所帮助。基本C++没有编码,你必须在更高的层次上处理自己。我确实认识其中的一些关键字,但如何在代码中实际使用它。。。另外,UTF-16 LE和UTF-16是如何比较的?@fge使用或查看BOM。@Cubbi这不是我真正的问题;假设我在LE或BE平台上使用u;我能保证结果一致吗?@lge如果您将u文本重新解释为char*,您将得到LE,或者取决于刚刚在IBM和x86上测试的平台,以确保我有一个更手动的版本,该代码不使用codecvt,而是手动执行utf8解码。它通过了cppgm测试,但可能没有100%的健壮性,它也大约长20倍:如果你想看它,请点击我。好的,现在,假设我有一个初始编码为UTF-32的文件,我想用ISO-8859-1在另一个文件中重写它,并检查错误?我有一个更手动版本的代码,它不使用codecvt,但手动进行utf8解码。它通过了cppgm测试,但可能没有100%的健壮性,它也大约长20倍:如果你想看它,请点击我。好的,现在,假设我有一个文件的初始编码是UTF-32,我想用ISO-8859-1在另一个文件中重写它,并检查错误?嗯,里面有很多东西。。。你说的窄编码是什么意思?@fge“窄”与“宽”相对。区域设置的狭义编码是用于字符字符串的编码。嗯,里面有很多东西。。。你说的窄编码是什么意思?@fge“窄”与“宽”相对。区域设置的狭义编码是用于字符字符串的编码。