консольное приложение может использовать разные способы вывода.
- для консоли ручки можно использовать
WriteConsoleW
для вывода уже в UNICODE
.
- , если мы хотим использовать
WriteConsoleA
или WriteFile
для консоли ручки нужно сначала преобразовать UNICODE
текст Многобайтовыестроки по WideCharToMultiByte
с CodePage :=
GetConsoleOutputCP()
- если мы не
UNICODE
текст изначально для выхода (скажем UTF-8
или Ansi
), нужно сначала преобразовать его в UNICODE
по MultiByteToWideChar
(с CP_UTF8
или CP_ACP
), а затем уже снова преобразовать его в многобайтную WideCharToMultiByte(GetConsoleOutputCP(), ..)
обычно (по умолчанию) 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
(текущий system locale). если у вас есть CP437
- Иврит и русские символы будут потеряны, если использовать UNICODE
->CP_OEMCP
, нужно только прямое выход с юникодом в консоль и файл. это возможно - зависимость от конкретного применения. для скажем route.exe
это невозможно. для ipconfig.exe
это возможно, потому что он всегда писать на консоль в формате Юникод, и может записать в файл также в unicode
или utf-8
, если вы установите "OutputEncoding"
в "Unicode"
или "UTF-8"
ReadFile возвращает байты, он не знает, что такое Unicode. Покажите, как обрабатывается его буфер. –
Я проверил возвращенные байты от отладчика, и они закодированы в CP437, причем иврит/русские символы заменены фактическими '?' S. Поскольку символы потеряны, обработка не восстановит это. Я хотел знать, как cmd.exe (или окно консоли?) Удается правильно захватить эти символы. – Jonathan
поэтому преобразуйте его в Юникод с помощью 'MultiByteToWideChar (CP_OEMCP,' - символы не потеряны – RbMm