控制台应用程序可以使用不同的方式进行输出。
通常(默认情况下)GetConsoleOutputCP() 返回与GetOEMCP() 相同的值,因此在MultiByteToWideChar 和WideCharToMultiByte 中具有与CP_OEMCP 相同的效果(此常量值转换为GetOEMCP())
当输出句柄被重定向到一个文件时,只需要使用WriteFile。但是应用程序可以以任何格式将数据写入文件:UNICODE、Ansi (CP_ACP)、UTF-8 (CP_UTF8) 等。将使用什么格式 - 非常取决于具体的应用程序。你无法完全控制这一点。通常你会收到CP_OEMCP 编码的多字节输出。然后您需要决定如何处理它 - 首先您需要更快地将其转换为 UNICODE 并使用 unicode 表单。如果您需要Ansi - 您将需要进行其他一次转换。
说如果你尝试在CP_OEMCP 编码中使用管道输出和OutputDebugStringA - 你得到非英文文本的错误(不可读)输出。
但经过 2 次转换后 CP_OEMCP -> UNICODE -> CP_ACP 您可以使用 OutputDebugStringA 更正显示的文本
但是因为 OutputDebugStringW 存在 - 这里只需要 UNICODE 转换
还有一些应用程序具有用于控制输出到文件格式的特殊选项。说ipconfig.exe 寻找"OutputEncoding" 环境变量并依赖于它的字符串值("Unicode"、"Ansi"、"UTF-8")产生不同的输出。默认情况下(如果此环境变量不存在或未知值)CP_OEMCP 使用
管道读取过程的示例。假设输入数据采用CP_OEMCP 编码:
void OnRead(PVOID buf, ULONG cbTransferred)
{
if (cbTransferred)
{
if (int len = MultiByteToWideChar(CP_OEMCP, 0, (PSTR)buf, cbTransferred, 0, 0))
{
PWSTR pwz = (PWSTR)alloca((1 + len) * sizeof(WCHAR));
if (len = MultiByteToWideChar(CP_OEMCP, 0, (PSTR)buf, cbTransferred, pwz, len))
{
if (g_bUseAnsi)
{
if (cbTransferred = WideCharToMultiByte(CP_ACP, 0, pwz, len, 0, 0, 0, 0))
{
PSTR psz = (PSTR)alloca(cbTransferred + 1);
if (cbTransferred = WideCharToMultiByte(CP_ACP, 0, pwz, len, psz, cbTransferred, 0, 0))
{
DoPrint(psz, cbTransferred, OutputDebugStringA);
}
}
}
else
{
DoPrint(pwz, len, OutputDebugStringW);
}
}
}
}
}
// debugger can incomplete print too big buffer, so split it on small chunks
template<typename T> void DoPrint(T* p, ULONG len, void (WINAPI* fnOutput)(const T*))
{
ULONG cb;
T* q = p;
do
{
cb = min(len, 256);
q = p + cb;
T c = *q;
*q = 0;
fnOutput(p);
*q = c;
p = q;
} while (len -= cb);
}
关于您的具体案例 - ipconfig.exe 使用 WriteConsoleW 输出到控制台。因此它不依赖于当前的系统区域设置,并且可以更正显示多语言文本。但是另一个工具,如route.exe 使用WriteFile 输出(既用于控制台也用于文件)并在此UNICODE 文本之前由WideCharToMultiByte(CP_OEMCP,..) 转换为多字节 - 结果这里会出现问题,如果尝试显示字符CP_OEMCP 代码页(当前系统区域设置)中不存在。如果你有CP437 - 如果使用UNICODE -> CP_OEMCP,希伯来语和俄语字符将丢失,只需要使用unicode直接输出到控制台和文件。这可能吗 - 取决于具体应用程序。比如说route.exe 这是不可能的。对于ipconfig.exe,这是可能的,因为它始终以 unicode 格式写入控制台,并且如果您将 "OutputEncoding" 设置为 "Unicode" 或 "UTF-8",也可以以 unicode 或 utf-8 写入文件