排版撇号 + 宽字符串文字破坏了我的 wofstream (C++)

Posted

技术标签:

【中文标题】排版撇号 + 宽字符串文字破坏了我的 wofstream (C++)【英文标题】:Typographic apostrophe + wide string literal broke my wofstream (C++) 【发布时间】:2009-05-03 01:59:36 【问题描述】:

在处理不祥的印刷撇号 (') 时,我刚刚遇到了一些奇怪的行为,而不是打字机撇号 (')。与宽字符串文字一起使用时,撇号会中断 wofstream。

此代码有效

ofstream file("test.txt");
file << "A’B" ;
file.close();

==> A'B

此代码有效

wofstream file("test.txt");
file << "A’B" ;
file.close();

==> A'B

此代码失败

wofstream file("test.txt");
file << L"A’B" ;
file.close();

==> 一个

此代码失败...

wstring test = L"A’B";
wofstream file("test.txt");
file << test ;
file.close();

==> 一个

有什么想法吗?

【问题讨论】:

以什么方式失败?例外? 字符串被截断。 【参考方案1】:

您应该在使用 wofstream 之前“启用”语言环境:

std::locale::global(std::locale()); // Enable locale support 
wofstream file("test.txt");
file << L"A’B";

因此,如果您有系统语言环境en_US.UTF-8,那么文件test.txt 将包括 utf8 编码数据(4 个字节),如果您有系统语言环境en_US.ISO8859-1,那么它将将其编码为 8 位编码(3 个字节),除非 ISO 8859-1 错过了这样的字符。

wofstream file("test.txt");
file << "A’B" ;
file.close();

此代码有效,因为"A’B" 实际上是 utf-8 字符串,而您保存 utf-8 一个字节一个字节的字符串到文件。

注意:我假设您使用的是类似 POSIX 的操作系统,并且您的默认语言环境与默认语言环境“C”不同。

【讨论】:

std::locale::global(std::locale("french"));作品。我想我现在明白了(或开始明白了)。通常在处理没有'L'的Unicode字符(太模糊......我知道)时,编译器(VS)会警告我“由universal-character-name表示的字符......不能在当前代码页中表示” .所以这次我很惊讶没有看到这个警告,所以我认为有问题。另外我认为/认为 UTF-8 仅对 128 US-ASCII 使用 1 字节编码 ... 第一个:UTF-8 与 US-ASCII 兼容。我其实不知道VS如何表示unicode charrecters,gcc默认使用utf-8,VS可能使用local charset。但是一般的想法是,您需要设置将宽字符转换为区域设置编码 8 位字符的区域设置。在 unix 下,这通常是 utf8【参考方案2】:

您确定不是您的编译器对源文件中的 unicode 字符的支持“损坏”了吗?如果您使用\x 或类似方法对字符串文字中的字符进行编码怎么办?您的源文件是否以任何编码可能对您的编译器为wchar_t 进行编码?

【讨论】:

令我困惑的是,当使用 unicode (mariusbancila.ro/blog/?p=135) wofstream 和 ' 时可以正常工作。但是为什么没有 unicode 的 ofstream 也可以呢? "unicode" 太模糊了。您可以使用例如带有 ofstream 的 UTF-8,它仍然是 unicode,但你不会使用 wchar_ts。同样,这很可能是源文件的编码与您实际放入字符串文字的内容之间的交互,以及您的编译器期望/认为您的源文件编码的内容。博文使用的是windows API,你在windows上使用VC++吗?【参考方案3】:

尝试将流插入字符包装在try-catch 块中,并告诉我们它会抛出什么异常(如果有)。

我不确定这里发生了什么,但无论如何我都会骚扰猜测。印刷撇号可能有一个适合一个字节的值。这适用于"A’B",因为它盲目地复制字节而不用担心底层编码。但是,对于L"A’B",依赖于实现的编码因素开始发挥作用。它可能找不到正确的 UTF-16(如果您在 Windows 上)或 UTF-32(如果您在 *nix/Mac 上)值来存储此特定字符。

【讨论】:

以上是关于排版撇号 + 宽字符串文字破坏了我的 wofstream (C++)的主要内容,如果未能解决你的问题,请参考以下文章

Java用'(撇号/单引号)和\(反斜杠)一起替换问题

如何在 PHP“回声”中插入带有撇号和其他特殊字符的文本? [复制]

HTML属性可以有撇号吗

url 编码的正斜杠破坏了我的 codeigniter 应用程序

iOS文字排版概念(字符和字形)

Android Studio - 破坏了我的 AVD 路径,破坏了我的模拟器