じゃあウンチクでも・・・
言語、地域、エンコーディング=ロケールは古代からとても厄介で面倒な問題があると思います。
デフォルトが何であるかとか標準が何であるか関係なく、「何を正しいと信じればいいのか?」があんまり明確でない時代が長く続いていたからです(もしかしたら今も…)。
端末入力(バイナリ)から得られた文字列が一体どんなエンコーディングなのか?
端末出力(バイナリ)にどんなエンコーディングで出力すればいいのか?
の正しい定義がないということです。
今回お題はWindowsということなので、Windowsで考えると、
端末のエンコーディング=コードページが分かればいいのでは?と
GetConsoleCP()
とか GetConsoleOutputCP()
とかに飛びつくと、、、
c++
1#include <windows.h>
2#include <iostream>
3int main() {
4 std::cout << ::GetConsoleCP() << std::endl;
5 return 0;
6}
これを例えばコマンドプロンプトで実行して、
cmd
1C:\>chcp
2現在のコード ページ: 932
3
4C:\>.\hoge.exe
5932
6
7C:\>chcp 65001
8Active code page: 65001
9
10C:\>.\hoge.exe
1165001
12
13C:\>
これが正しいと思っていると実はそうではなく、「コンソールじゃないアプリでは?」と言われるかもしれません。
例えばGetACP()
を使えとか言われたなら、、、
c++
1#include <windows.h>
2#include <iostream>
3int main() {
4 std::cout << ::GetACP() << std::endl;
5 return 0;
6}
で
cmd
1C:\>chcp
2現在のコード ページ: 932
3
4C:\>.\hoge.exe
5932
6
7C:\>chcp 65001
8Active code page: 65001
9
10C:\>.\hoge.exe
11932
12
13C:\>
この関数が使われてるのかは知りませんが、例えばpythonでこんなコードを書くと、、、
python
1import subprocess
2print(subprocess.run('echo 日本語', shell=True, capture_output=True, text=True).stdout)
で
cmd
1C:\>chcp
2現在のコード ページ: 932
3
4C:\>python --version
5Python 3.11.2
6
7C:\>type hoge.py
8import subprocess
9print(subprocess.run('echo 譌・譛ャ隱・, shell=True, capture_output=True, text=True).stdout)
10
11C:\>python hoge.py
12日本語
13
14
15C:\>chcp 65001
16Active code page: 65001
17
18C:\>type hoge.py
19import subprocess
20print(subprocess.run('echo 日本語', shell=True, capture_output=True, text=True).stdout)
21
22C:\>>python hoge.py
23Exception in thread Thread-1 (_readerthread):
24Traceback (most recent call last):
25 File "threading.py", line 1038, in _bootstrap_inner
26 File "threading.py", line 975, in run
27 File "subprocess.py", line 1552, in _readerthread
28UnicodeDecodeError: 'cp932' codec can't decode byte 0x9e in position 8: illegal multibyte sequence
29None
30
31C:\>python
32Python 3.11.2 (tags/v3.11.2:878ead1, Feb 7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)] on win32
33>>> import locale
34>>> locale.getlocale()
35('Japanese_Japan', '932')
36>>>
ということなわけです。Unix系との対比で考えると、setlocale()
だよなぁとも思うわけで、WindowsのCRTで
の挙動を見ると、
ロケールを既定に設定します。これはオペレーティング システムから取得したユーザー既定の ANSI コード ページです。 ロケール名は、GetUserDefaultLocaleName によって返される値に設定されます。 コード ページは、GetACP によって返される値に設定されます。
そうなるのもアリかなぁと思います。コンソールを追求すると他と合わなくなり、「動作が統一されない!」といろいろお怒りの方が現れるわけで、とても厄介で面倒だなぁと思います。
デフォルト変えるのもいいのですが、何か統一の指針となる正しい動作も一緒に欲しい気がしますね。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。