Windowsにおけるコンソールアプリの標準出力が実は、コードページ932(MS-DOS OEM)をデフォルトとしている、と最近気付いたお話です。
何となく知ってはいましたが、何を意味するのかわかっていませんでした。これが理由でwprintf等を使ってさえ、setlocaleしないと日本語が表示できなかったのです。
さてこれまた最近、リダイレクトに興味を持ちました。Microsoftが提供しているサンプルがあるのですが、これのUnicode入力をどうしたものかと調べてみたのです。
その中で上記CP932を理解したのですが、子プロセスになるコンソールアプリをUnicodeでコンパイルしようと何しようと、親プロセスのReadFileには常に8ビットで文字が取得されました。
唯一違ったのがcmd.exe /uによるUnicodeパイプ出力のコンソールで(ただし内部コマンド限定)、このことは子プロセス側で対応できる(すべき)だろうことを示唆していました。
ならば標準関数以外の方法でUnicode出力すればよいはず、ということで見つけたのがWriteConsoleでした。コンソール系APIは触ったことがなかったので未知の世界です。
WriteConsoleを使えば、setlocaleしなくても日本語を表示できたのですが、説明にある通りリダイレクトされたハンドルには出力できませんでした。代わりに、WriteFileで親プロセスにUnicode文字列を渡すことはできました。
# WriteFileをコンソールに使うと、8ビット幅のつもりで
# 文字列を出力されるお馴染みの問題が出ます
最終的に、GetStdHandle(STD_OUTPUT_HANDLE)で取得されるハンドルをGetFileTypeに渡し、FILE_TYPE_CHARの場合にWriteConsole、そうでなければWriteFileすることで解決しました。
...いびつなOSですね。
何となく知ってはいましたが、何を意味するのかわかっていませんでした。これが理由でwprintf等を使ってさえ、setlocaleしないと日本語が表示できなかったのです。
さてこれまた最近、リダイレクトに興味を持ちました。Microsoftが提供しているサンプルがあるのですが、これのUnicode入力をどうしたものかと調べてみたのです。
その中で上記CP932を理解したのですが、子プロセスになるコンソールアプリをUnicodeでコンパイルしようと何しようと、親プロセスのReadFileには常に8ビットで文字が取得されました。
唯一違ったのがcmd.exe /uによるUnicodeパイプ出力のコンソールで(ただし内部コマンド限定)、このことは子プロセス側で対応できる(すべき)だろうことを示唆していました。
ならば標準関数以外の方法でUnicode出力すればよいはず、ということで見つけたのがWriteConsoleでした。コンソール系APIは触ったことがなかったので未知の世界です。
WriteConsoleを使えば、setlocaleしなくても日本語を表示できたのですが、説明にある通りリダイレクトされたハンドルには出力できませんでした。代わりに、WriteFileで親プロセスにUnicode文字列を渡すことはできました。
# WriteFileをコンソールに使うと、8ビット幅のつもりで
# 文字列を出力されるお馴染みの問題が出ます
最終的に、GetStdHandle(STD_OUTPUT_HANDLE)で取得されるハンドルをGetFileTypeに渡し、FILE_TYPE_CHARの場合にWriteConsole、そうでなければWriteFileすることで解決しました。
...いびつなOSですね。
コメントする