web-dev-qa-db-ja.com

Windowsのc ++コンソールアプリケーションからUTF-8を印刷するにはどうすればよいですか

英語版Windows(XP、Vista、または7)でVisual Studio2008を使用してコンパイルされたC++コンソールアプリケーションの場合。 coutまたはwcoutを使用して、コンソールに印刷し、UTF-8でエンコードされた日本語を正しく表示することはできますか?

19
Paul Dixon

Windowsコンソールは、デフォルトで OEMコードページ を使用して出力を表示します。

コードページをUnicodeに変更するには、コンソールにchcp 65001と入力するか、プログラムでコードページを SetConsoleOutputCP

コンソールのフォントを、Unicode範囲のグリフを持つフォントに変更する必要があることに注意してください。

8
dtb

MVP Michael Kaplanからの記事です コンソールからUTF-16を正しく出力する方法について。 UTF-8をUTF-16に変換して出力することができます。

5
sbi

私は実際にコンソールのコードページをUTF8に設定しようとしたことはありません(なぜそれが機能しないのかわかりません...コンソールは他のマルチバイトコードページを問題なく処理できます)が、見るべき関数がいくつかありますup:SetConsoleCPおよびSetConsoleOutputCP。

また、文字を表示できるコンソールフォントを使用していることも確認する必要があります。 SetCurrentConsoleFontEx 関数がありますが、Vista以降でのみ使用できます。

お役に立てば幸いです。

4
ijprest

これは機能するはずです:

#include <cstdio>
#include <windows.h>

#pragma execution_character_set( "utf-8" )

int main()
{
    SetConsoleOutputCP( 65001 );
    printf( "Testing unicode -- English -- Ελληνικά -- Español -- Русский. aäbcdefghijklmnoöpqrsßtuüvwxyz\n" );
}

何かに影響するかどうかはわかりませんが、ソースファイルはUnicode(署名付きのUTF-8)-コードページ65001at[〜#〜 ] file [〜#〜]->高度な保存オプション...

プロジェクト->プロパティ->構成プロパティ->General->Character SetUse Unicode Character Setに設定されます。

コンソールフォントをLucida Consoleに変更する必要があると言う人もいますが、私の側では両方のConsolasおよびLucida Console

2
Slav

追加情報のためだけに:

「ANSI」は、win32アプリケーションに使用されるwindows-125xを指し、「OEM」は、コンソール/ MS-DOSアプリケーションによって使用されるコードページを指します。
現在アクティブなコードページは、関数GetOEMCP()およびGetACP()を使用して取得できます。

コンソールに何かを正しく出力するには、次のことを行う必要があります。

  1. 現在のOEMコードページが出力する文字をサポートしていることを確認してください
    (必要に応じて、SetConsoleOutputCPを使用して適切に設定してください)

  2. 文字列を現在のANSIコード(win32)からコンソールOEMコードページに変換します

これを行うためのいくつかのユーティリティは次のとおりです。

// Convert a UTF-16 string (16-bit) to an OEM string (8-bit) 
#define UNICODEtoOEM(str)   WCHARtoCHAR(str, CP_OEMCP)

// Convert an OEM string (8-bit) to a UTF-16 string (16-bit) 
#define OEMtoUNICODE(str)   CHARtoWCHAR(str, CP_OEMCP)

// Convert an ANSI string (8-bit) to a UTF-16 string (16-bit) 
#define ANSItoUNICODE(str)  CHARtoWCHAR(str, CP_ACP)

// Convert a UTF-16 string (16-bit) to an ANSI string (8-bit)
#define UNICODEtoANSI(str)  WCHARtoCHAR(str, CP_ACP)


/* Convert a single/multi-byte string to a UTF-16 string (16-bit).
 We take advantage of the MultiByteToWideChar function that allows to specify the charset of the input string.
*/
LPWSTR CHARtoWCHAR(LPSTR str, UINT codePage) {
    size_t len = strlen(str) + 1;
    int size_needed = MultiByteToWideChar(codePage, 0, str, len, NULL, 0);
    LPWSTR wstr = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * size_needed);
    MultiByteToWideChar(codePage, 0, str, len, wstr, size_needed);
    return wstr;
}


/* Convert a UTF-16 string (16-bit) to a single/multi-byte string.
 We take advantage of the WideCharToMultiByte function that allows to specify the charset of the output string.
*/
LPSTR WCHARtoCHAR(LPWSTR wstr, UINT codePage) {
    size_t len = wcslen(wstr) + 1;
    int size_needed = WideCharToMultiByte(codePage, 0, wstr, len, NULL, 0, NULL, NULL);
    LPSTR str = (LPSTR) LocalAlloc(LPTR, sizeof(CHAR) * size_needed );
    WideCharToMultiByte(codePage, 0, wstr, len, str, size_needed, NULL, NULL);
    return str;
}
1

アプリ起動コンソールで、デフォルトのOEM437CPに設定します。 Unicodeテキストをstdoutに出力しようとしましたが、コンソールはUTF8変換に切り替えられました_setmode(_fileno(stdout)、_ O_U8TEXT); Lucida TT fontでも、画面に表示されませんでした。コンソールがファイルにリダイレクトされた場合、正しいUTF8ファイルが作成されました。

ついにラッキーでした。 「info.FontFamily = FF_DONTCARE;」という1行を追加しました。そしてそれは今働いています。これがあなたの助けになることを願っています。

void SetLucidaFont()
{
    HANDLE StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_FONT_INFOEX info;
    memset(&info, 0, sizeof(CONSOLE_FONT_INFOEX));
    info.cbSize = sizeof(CONSOLE_FONT_INFOEX);              // prevents err=87 below
    if (GetCurrentConsoleFontEx(StdOut, FALSE, &info))
    {
        info.FontFamily   = FF_DONTCARE;
        info.dwFontSize.X = 0;  // leave X as zero
        info.dwFontSize.Y = 14;
        info.FontWeight   = 400;
        _tcscpy_s(info.FaceName, L"Lucida Console");
        if (SetCurrentConsoleFontEx(StdOut, FALSE, &info))
        {
        }
    }
}
1
adspx5

コンソールでchcp 65001と入力して、コードページをUTF-8のコードページに変更します。

0