【问题标题】:streams with default utf8 handling具有默认 utf8 处理的流
【发布时间】:2013-07-21 09:24:36
【问题描述】:

我读到在某些环境中std::string 内部使用 UTF-8。而在我的平台 Windows 上,std::string 仅是 ASCII。可以使用std::locale 更改此行为。我的 STL 版本没有,或者至少我找不到,用于字符串的 UTF-8 方面。不过,我确实有一个方面可用于 fstream 类集。

编辑: 当我说“在内部使用 UTF-8”时,我指的是像 std::basic_filebuf::open() 这样的方法,在某些环境中它接受 UTF-8 编码的字符串。我知道这并不是真正的std::string 问题,而是某些操作系统本身使用UTF-8。我的问题应该理解为“您的实现如何处理无效序列的代码转换?”。

这些流如何处理其他平台/实现上的无效代码序列?

在我的 UTF8 facet 文件中,它只是返回一个错误,从而阻止读取更多的流。我本以为将错误更改为 Unicode "Invalid char" 0xfffd 值是一个更好的选择。

我的问题不仅限于UTF-8,那么无效的UTF-16 代理对呢?

让我们举个例子。假设您打开一个UTF-8 编码文件,其中UTF-8wchar_t locale。您的实现如何处理无效的UTF-8 序列? 或者,std::wstring 并将其打印到 std::cout,这一次使用一个单独的代理。

【问题讨论】:

  • 这取决于用例。有时您希望发出错误信号(当无效数据完全不可接受时);有时你想要 U+FFFD;有时你想简单地丢弃坏数据;有时你想要别的东西。
  • @R.MartinhoFernandes 你的实现是否至少让你可以选择告诉它如何处理这种情况?
  • 在您的示例中-请您给出确切的编解码器方面吗?是:std::codecvt_utf8<wchar_t>? - 你使用的是什么确切的流? std::wifstream ?您打算使用什么确切的字符串类型? std::wstringstd::string ?
  • @IwanAucamp 我没有针对这些方面的 C++11 扩展。虽然我确实有一个仅用于文件流的std::codecvt< char32_t, char, mbstate_t > 方面。
  • @Waldermort 你用的是哪个?

标签: c++ unicode c++11 stream locale


【解决方案1】:

std::string 应该是编码不可知的:http://en.cppreference.com/w/cpp/string/basic_string - 所以它不应该验证代码点/数据 - 你应该能够在其中存储任何二进制数据。

编码真正产生影响的唯一地方是计算字符串长度和逐个字符地迭代字符串 - 并且语言环境在这两种情况下都应该没有影响。

而且 - 如果可以完全避免使用 std::locale 可能不是一个好主意 - 它在所有平台或标准库的所有实现上都不是线程安全的,因此在使用它时必须小心。这样做的效果也非常有限,而且可能根本不是您所期望的。

【讨论】:

  • 这不能回答我的问题,而且是不相关的,而且是错误的。 locale 的效果非常明显,甚至在大多数流处理操作中都需要。
  • @Waldermort 不,没有错——std::string 确实根本不知道或关心字符编码。它没有“内部编码”。它在很大程度上是一个字节容器——例如,std::string::length() 总是返回字节数,而不是字符数。
  • @Waldermort std::string 没有“幕后”处理编码。你的问题并没有问任何关于 std::wstringchar16_tchar32_t 字符串的问题。
  • @Waldermort 是的,std::string 根本不使用语言环境。 std::codecvt 被某些流使用,但默认 std::codecvt<char,char,std::mbstate_t> 是一个无操作转换器;它只是传递字节而不做任何事情。控制台选择如何处理要求显示的无效序列。
  • @Waldermort strings 不是 streams
【解决方案2】:

我读到在某些环境中 std::string 内部使用使用 UTF-8。

C++ 程序可以选择使用std::string 在任何符合标准的平台上保存 UTF-8 字符串。

而在我的 Windows 平台上,std::string 只是 ASCII。

这是不正确的。在 Windows 上,您可以根据需要使用std::string 来保存 UTF-8 字符串,std::string 不限于在任何符合标准的平台上保存 ASCII。

可以使用 std::locale 更改此行为。

不,std::string 的行为不受语言环境库的影响。

std::stringchars 的序列。在包括 Windows 在内的大多数平台上,char 是 8 位的。因此,您可以使用std::string 来保存 ASCII、Latin1、UTF-8 或任何使用 8 位或更少代码单元的字符编码。 std::string::length 返回如此持有的代码单元的数量,std::string::operator[] 将返回第 i 个代码单元。

对于保存 UTF-16,您可以使用 char16_tstd::u16string

对于保存 UTF-32,您可以使用 char32_tstd::u32string

【讨论】:

    【解决方案3】:

    假设您使用 UTF-8 到 wchar_t 语言环境打开一个 UTF-8 编码文件。您的实现如何处理无效的 UTF-8 序列?

    通常没有人会在其他平台上转换为wchar_t 或其他宽字符类型,但可用于此的标准方面都表示读取错误,导致流停止工作,直到错误被清除。

    【讨论】:

    • 据我所知,这是必需的行为。
    猜你喜欢
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 2018-11-25
    • 1970-01-01
    • 2011-10-16
    • 1970-01-01
    相关资源
    最近更新 更多