- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我的问题似乎让人们感到困惑。这是一些具体的东西:
我们的代码执行以下操作:
FILE * fout = _tfsopen(_T("丸穴種類.txt"), _T("w"), _SH_DENYNO);
_fputts(W2T(L"刃物種類\n"), fout);
fclose(fout);
在 MBCS 构建目标下,上面的代码为代码页 932 生成了一个正确编码的文件(假设运行时 932 是系统默认代码页)。
在 UNICODE 构建目标下,上面生成了一个充满 ???? 的垃圾文件。
我想定义一个符号,或者使用编译器开关,或者包含一个特殊的头文件,或者链接到给定的库,以便在构建目标为 UNICODE 时使上述内容继续工作而不更改源代码。
这是过去存在的问题:
FILE*
streams can be opened in t(ranslated) or b(inary) modes. Desktop applications can be compiled for UNICODE or MBCS (under Windows).If my application is compiled for MBCS, then writing MBCS strings to a "wt" stream results in a well-formed text file containing MBCS text for the system code page (i.e. the code page "for non Unicode software").
Because our software generally uses the _t versions of most string & stream functions, in MBCS builds output is handled primarily by
puts(pszMBString)
or something similarputc
etc. SincepszMBString
is already in the system code page (e.g. 932 when running on a Japanese machine), the string is written out verbatim (although line terminators are massaged byputs
andgets
automatically).However, if my application is compiled for UNICODE, then writing MBCS strings to a "wt" stream results in garbage (lots of "?????" characters) (i.e. I convert the UNICODE to the system's default code page and then write that to the stream using, for example,
fwrite(pszNarrow, 1, length, stream)
).
I can open my streams in binary mode, in which case I'll get the correct MBCS text... but, the line terminators will no longer be PC-style CR+LF, but instead will be UNIX-style LF only. This, because in binary (non-translated) mode, the file stream doesn't handle the LF->CR+LF translation.
But what I really need, is to be able to produce the exact same files I used to be able to produce when compiling for MBCS: correct line terminators and MBCS text files using the system's code page.
Obviously I can manually adjust the line terminators myself and use binary streams. However, this is a very invasive approach, as I now have to find every bit of code throughout the system that writes text files, and alter it so that it does all of this correctly. What blows my mind, is that UNICODE target is stupider / less capable than the MBCS target we used to use! Surely there is a way to toggle the C library to say "output narrow strings as-is but handle line terminators properly, exactly as you'd do in MBCS builds"?!
最佳答案
遗憾的是,这是一个巨大的话题,值得专门写一本小书。那本书基本上需要为每个希望构建的目标平台(Linux、Windows [flavor]、Mac 等)专门写一章。
我的回答只涉及 Windows 桌面应用程序,为 C++ 编译,有或没有 MFC。请注意:这与希望使用系统默认代码页(即非 Unicode 软件的代码页)从 UNICODE 构建中读入和写出 MBCS(窄)文件有关。 如果要从 UNICODE 构建中读取和写入 Unicode 文件,则必须以二进制模式打开文件,并且必须手动处理 BOM 和换行符转换(即在输入时,必须跳过 BOM(如果有),并且两者将外部编码转换为 Windows Unicode [即 UTF-16LE],并将任何 CR+LF 序列仅转换为 LF;对于输出,您必须编写 BOM(如果有),并将 UTF-16LE 转换为任何目标编码你想要的,再加上你必须将 LF 转换为 CR+LF 序列才能使其成为格式正确的 PC 文本文件)。
注意 MS 的标准 C 库的 puts 和 gets 以及 fwrite 等等,如果以文本/翻译模式打开,它们将在写入时将任何 0x0D 转换为 0x0A 0x0D 序列,在读取时反之亦然,无论无论您是读取或写入单个字节、宽字符还是随机二进制数据流——都无关紧要,所有这些功能归结为在文本/翻译模式下进行盲字节转换! !!
另请注意,许多 Windows API 函数在内部使用 CP_ACP,对其行为没有任何外部控制(例如 WritePrivateProfileString()
)。因此,人们可能希望确保所有库都使用相同的字符区域设置运行的原因:CP_ACP 而不是其他某个区域设置,因为您无法控制某些功能行为,您被迫遵守他们的选择或不使用
如果使用 MFC,需要:
// force CP_ACP *not* CP_THREAD_ACP for MFC CString auto-conveters!!!
// this makes MFC's CString and CStdioFile and other interfaces use the
// system default code page, instead of the thread default code page (which is normally "c")
#define _CONVERSION_DONT_USE_THREAD_LOCALE
对于 C++ 和 C 库,必须告诉库使用系统代码页:
// force C++ and C libraries based on setlocale() to use system locale for narrow strings
// (this automatically calls setlocale() which makes the C library do the same thing as C++ std lib)
// we only change the LC_CTYPE, not collation or date/time formatting
std::locale::global(std::locale(str(boost::format(".%||") % GetACP()).c_str(), LC_CTYPE));
在包含任何其他 header 之前,我在所有预编译 header 中执行了#define
。我在 main(或其等价物)中设置了全局语言环境,一次用于整个程序(您可能需要为将要执行 I/O 或字符串转换的每个线程调用它)。
构建目标是 UNICODE,对于我们的大部分 I/O,我们在通过 CStringA(my_wide_string)
输出之前使用显式字符串转换。
另一件应该注意的事情是,在 VS C++ 下的 C 标准库中有两组不同的多字节函数 - 一组使用线程的区域设置进行操作,另一组使用称为 _setmbcp()
(您可以通过 _getmbcp()
查询。这是用于所有窄字符串解释的实际代码页(不是语言环境)(注意:这始终是初始化为 CP_ACP
,即 GetACP()
由 VS C++ 启动代码)。
有用的引用资料:
- the-secret-family-split-in-windows-code-page-functions
- Sorting it all out (explains that there are four different locales in effect in Windows)
- MS offers some functions that allow you to set the encoding to use directly, but I didn't explore them
- An important note about a change to MFC that caused it to no longer respect CP_ACP, but rather CP_THREAD_ACP by default starting in MFC 7.0
- Exploration of why console apps in Windows are extreme FAIL when it comes to Unicode I/O
- MFC/ATL narrow/wide string conversion macros (which I don't use, but you may find useful)
- Byte order marker, which you need to write out for Unicode files of any encoding to be understood by other Windows software
关于c++ - 如何从 UNICODE 应用程序写入 MBCS 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18359750/
我有一个 MFC 应用程序,其中字符集是“未设置”。在具有多字节字符集代码页的操作系统上运行此应用程序有哪些相关风险? 最佳答案 “字符集:未设置”选项未定义 _MBCS也不_UNICODE .这意味
我正在寻找一个正则表达式来匹配 C++ 项目中的 MBCS 字符串。这些是包含在双引号中的字符串,没有 L"..."或 _T("...")说明符。任何一行代码都可以有多个引号。字符串可以包含不应结束匹
我在使用 Python 脚本打开包含元音变音字符的文件时遇到问题。当然,我认为我可以通过 unicode utf8 修复来纠正这个问题,但事实并非如此...... 我最终使用了mbcs(默认为cp12
我想检测以“HKEY_LOCAL_MACHINE\SOFTWARE\blah\SetupPath”开头的注册表项,如果可能的话读取到 CString。 我在 MSDN 上看到了 RegOpenKeyE
我有一个用 ISO C++ 编写的库。它不使用 Winapi、TCHAR 或类似的东西。我目前正在将其构建为字符集设置为 Unicode 的静态库。我打算将它链接到其他库,其中一些是使用 Unicod
我有一个 MBCS(多字节字符)MFC 应用程序,我从 stdafx.h 文件中删除了 #ifdefs,现在我的 MBCS 应用程序使用公共(public)控件 6。在互联网上我发现很多文章用户说一些
我的问题似乎让人们感到困惑。这是一些具体的东西: 我们的代码执行以下操作: FILE * fout = _tfsopen(_T("丸穴種類.txt"), _T("w"), _SH_DENYNO); _
我正在使用 VS2008 开发一个项目,该项目是在 MBCS 中编译的,但我需要使用一些 UTF-8 字符串来与某些 Web 服务进行交互。我编写了一个函数,它可以完美地与 Unicode 一起工作,
我有一个大型 MFC 应用程序,我正在扩展它以允许多语言输入。目前我需要允许用户在单个对话框的编辑框中输入 Unicode 数据。 有没有办法在不为整个应用程序打开 UNICODE 或 MBCS 的情
我想将我的 visual studio 项目从 MBCS 转换为 Unicode CS。但是我的源代码中有 900 个 const char 数组,有没有自动的方法来做到这一点?一行一行地做很多事情。
我搜索了一下,没有找到太多相关信息。我们需要为编码等提供最通用的支持,并希望确保 ANTLR 能够处理我们扔给它的任何东西。 最佳答案 Java VM 使用 16 位字符编码,因此 MBCS 流在读入
我有一个 vc++ dll,其编译时的字符集设置为“使用 Unicode 字符集”。现在我想在我的 vc++ exe 中使用这个 dll,其字符集是“使用多字节字符集”。我知道理论上没有什么可以阻止我
我正在尝试将包含来自位图文件的数据的 std::string 缓冲区转换为 std::wstring。 我正在使用 MultiByteToWideChar,但这不起作用,因为该函数在遇到第一个 '\0
我正在阅读 Windows 上的字符集和编码。我注意到在 Visual Studio 编译器(用于 C++)中有两个编译器标志,称为 MBCS 和 UNICODE。它们之间有什么区别?我没有得到的是
我有一个遗留应用程序使用 Window 的旧 MBCS。该软件是国际化的,并使用代码页使其适用于其他语言。我读过中文包含多字节字符。我的问题是,哪些以及如何在美国的计算机上生成它们?我需要这个进行测试
我正在使用 Visual C++ (VS2005) 并在多字节字符集 (MBCS) 中编译项目。但是,该程序需要通过 XMLRPC 与 Web 应用程序(使用 utf-8)进行通信。所以我想也许我可以
我使用 Visual Studio 打开了现有的 MFC 项目,并且在构建时收到以下错误消息: Error 1 error MSB8031: Use of MBCS encoding in MFC p
我正在使用一个生成 const char* 类型的以 UTF-8 空字符结尾的字符串的库。示例包括: MIGUEL ANTÓNIO DONA ESTEFÂNIA 我想将这两个 const char
我正在 Linux 上编写一个程序,它必须与现有的 Windows 程序交互。我无法修改 windows 程序的工作方式,但我必须与现有数据集成。该程序将通过 TCP 网络套接字接收原始数据结构。不幸
有人处理过使用 std::string 函数处理 MBCS 吗?例如在 C 中我可以这样做: p = _mbsrchr(path, '\\'); 但在 C++ 中我这样做: found = path.
我是一名优秀的程序员,十分优秀!