-
Notifications
You must be signed in to change notification settings - Fork 0
MS_ApplicationUnicodeMigration
- 戻る(文字コード)
アプリケーションの Unicode 対応
GUI アプリケーションの Unicode 対応
古いアプリケーションには、非 Unicode 対応の GUI アプリケーションが存在する。
-
拡張文字セットを扱うにはアプリケーションの Unicode 対応が必要である。
- 非 Unicode アプリケーションでは JIS2004 の拡張文字セットだけでなく、
Shift-JIS にない文字は全て入力できない。 - 但し、アプリの画面上で、明確に「?」表示になるので、
予期せず JIS2004 の拡張文字セットが入力されることもない。
- 非 Unicode アプリケーションでは JIS2004 の拡張文字セットだけでなく、
-
システムが Unicode に統一されている場合は、
エンコーディングされる箇所を意識する必要がある。

補足(「予期せず入力されない」という利点は失われつつある): 原文の
「非 Unicode アプリでは『?』になるので、予期せず入力されない」
という指摘は、当時の運用上の安心材料として的確だった。しかし現在は、入力経路が増えたためこの前提が崩れている。
【現在のデータの入り口】 ・Web フォーム(ブラウザは完全に Unicode) ・スマートフォン・タブレット(Unicode。絵文字も入る) ・CSV / Excel の取り込み ・API 経由(JSON は UTF-8 が既定) ・OCR、名刺読み取り、外部サービス連携 → 「画面から入らないから安全」は、もはや成立しない現在の対策は「入力を止める」から「正しく扱う」へ移った。
当時 現在 非 Unicode アプリで入力を物理的に止める 全経路を Unicode で通し、必要な箇所だけ検査する 「?」になるので気付く 文字のチェック方式 で明示的に検査する Shift_JIS 前提の設計 UTF-8 前提の設計 「気付かないうちに壊れる」のを防ぐという目的自体は今も重要で、
それを明示的な検査で実現するのが現在の形である。
- 非 Unicode アプリケーションでは、Shift-JIS にない文字の入力ができない
(これは、IME から、ウィンドウ プロシージャ経由でデータを正しく受け取れないため)。 - 例えば、JIS2004 で追加された拡張文字セット以外の、Shift-JIS にない
鱓(ごまめ)という文字を非 Unicode アプリケーションに入力して見ると、
この文字も入力できないことが確認できる。
[参考]:CyberLibrarian(図書館員のコンピュータ基礎講座参考資料) > 参考資料JIS補助漢字(JIS X 0212)
http://www.asahi-net.or.jp/~ax2s-kmtn/ref/jisx0212/jisx0212-4.html
・・・ 「鱓」は、JIS90(JIS X 0212)補正漢字
補足(仕組み): Win32 API には同じ関数の A 版と W 版があり、
これが「非 Unicode / Unicode アプリ」の実体である。【A 版】 …ANSI(=OS の既定コードページ。日本語なら CP932) 例: CreateWindowExA、SendMessageA、DefWindowProcA 【W 版】 …Wide(=UTF-16) 例: CreateWindowExW、SendMessageW、DefWindowProcW【非 Unicode アプリで文字が消える経路】 IME(内部は Unicode) ↓ 確定文字を WM_IME_CHAR / WM_CHAR で送る ウィンドウが A 版で登録されている ↓ OS が【UTF-16 → CP932 に変換して】渡す CP932 にない文字は「?」(0x3F)になる ↓ アプリには「?」しか届かない(元の文字は失われている)重要なのは「変換は OS が勝手に行う」点である。
アプリ側でどれだけ頑張っても、
ウィンドウが A 版である限り、文字は届く前に失われる。
原文が「ウィンドウ プロシージャ経由でデータを正しく受け取れないため」と
書いているのは、まさにこの構造を指している。
アプリケーションの Unicode 対応の方法
- [HOWTO] Visual Basic のフォームで UNICODE 文字列の読み込みと表示を行う方法
http://support.microsoft.com/kb/193540/ja
補足(VB6 の話である): この KB は **VB6(Visual Basic 6.0)**向けで、
VB.NET には該当しない。
内部表現 Unicode 対応 VB6 UTF-16 だが、フォームは A 版 API 非対応(回避策が要る) VB.NET / C# UTF-16( string)最初から対応済み .NET のコントロールはすべて W 版 API で作られているため、
Windows Forms / WPF / WinUI のいずれでも
Unicode 対応の作業は不要である。・.NET の string は最初から UTF-16 ・TextBox 等のコントロールは W 版 API を使う ・したがって、𠮷 も 髙 も 絵文字も、そのまま入力・保持できる現在の課題は「入力できるか」ではなく、
その先(DB、ファイル、連携先)で失われないかに移っている
(文字のチェック方式)。
-
アプリケーションの Unicode 対応は = ウィンドウ(ウィンドウ プロシージャ、
メッセージ ループ)の Unicode 対応である。- ウィンドウ(ウィンドウ プロシージャ、メッセージ ループ)を Unicode 対応させるには、
IsWindowUnicode 関数が True を返すウィンドウを作成する。 - また、IsWindowUnicode 関数が True を返す場合でも、
ウィンドウ プロシージャ、メッセージ ループで、メッセージを正しく処理する必要がある。
- ウィンドウ(ウィンドウ プロシージャ、メッセージ ループ)を Unicode 対応させるには、
-
ウィンドウ(ウィンドウ プロシージャ、メッセージ ループ)の Unicode 対応には、
以下が必要である。-
ウィンドウクラスの登録は、RegisterClassW 関数を使用する。
-
ウィンドウの作成は
- CreateWindowExA、CreateWindowExW 関数のどちらでも良い。
- ただし、エディット コントロールなどのコモン コントロール類や、
それをサブクラス化したウィンドウの場合は、CreateWindowExW 関数を使わなければならない。
-
ウィンドウ プロシージャでは DefWindowProcW 関数を使う。
-
サブクラス化している場合は、CallWindowProcW 関数を使う。
-
メッセージ ループでは、以下の関数を使用する。
- GetMessageW
- DispatchMessageW
- TranslateAcceleratorW
-
-
フロント周りは、ほぼ Unicode 対応が済んでいる。
- メモ帳
- WWW ブラウザなどのアプリケーション
- Office(Word、Excel、Powerpoint)
- 開発環境の標準入力コントロール
-
[参考]:Microsoft Learn
- IsWindowUnicode
https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-iswindowunicode - RegisterClass
https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-registerclassw - CreateWindowExA
https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-createwindowexa - DefWindowProc
https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-defwindowprocw - CallWindowProc
https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-callwindowprocw - GetMessage
https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getmessagew - DispatchMessage
https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-dispatchmessagew - TranslateAccelerator
https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-translateacceleratorw
- IsWindowUnicode
補足(原文の「ウィンドウクラスの登録が決め手」という指摘は正確): この
一連の記述は、Win32 の仕様を正しく捉えている。要点を補強しておく。【IsWindowUnicode が True になる条件】 ウィンドウの「クラス」を RegisterClassW で登録したこと ← CreateWindowEx の A/W は関係ない(原文の通り) 【なぜ A でも W でも良いのか】 CreateWindowEx の A/W が影響するのは 「ウィンドウ【タイトル】の文字列」の解釈だけ → ウィンドウ自体の性質はクラス登録時に決まる原文の「ただし」以降——コモン コントロールは W 版で作れ——も重要で、
これはコモン コントロールのクラスが
comctl32.dll 側で登録済み(A/W 両方ある)であるため、
CreateWindowExWを呼ぶことで W 版のクラスが選ばれる、という理屈である。現在の VC++ での書き方:
// プロジェクト設定で「Unicode 文字セットを使用する」を選ぶと // UNICODE / _UNICODE が定義され、A/W なしの名前が W 版に解決される #define UNICODE #define _UNICODE // 以降、RegisterClass / CreateWindowEx / DefWindowProc は // すべて自動的に W 版になるVisual Studio の既定は「Unicode 文字セット」であり、
新規プロジェクトでは対応済みである。
問題になるのは、「マルチバイト文字セット(MBCS)」で作られた古い資産を
引き継いだ場合だけである。【MBCS プロジェクトを Unicode 化する際の作業】 ① プロジェクト設定を「Unicode 文字セット」に変更 ② char / LPSTR → TCHAR / LPTSTR(または直接 wchar_t / LPWSTR) ③ "文字列" → _T("文字列") または L"文字列" ④ strlen / strcpy → _tcslen / _tcscpy(または wcslen / wcscpy) ⑤ ファイル I/O、DB アクセス、外部 DLL との境界を洗い出す ★ ⑤ が最も工数を食う。②~④ は機械的に置換できるMFC も既定で Unicode ビルドである。
VS 2015 以降、MBCS 版の MFC ライブラリは別途インストールが要る
(非推奨扱い)。
補足(この記事全体の現在的な意味): 原文が扱う
「アプリケーションの Unicode 化」は、
デスクトップ アプリの層ではほぼ完了した課題である。現在「Unicode 化」が問題になる場所は、以下に移っている。
層 現在の課題 データベース varchar→nvarchar、照合順序に_SC(サロゲート対応)ファイル連携 固定長・CSV が CP932 前提で作られている 外部システム連携 相手が CP932 しか受けない(文字のチェック方式 の可逆チェック) 帳票・印刷 フォントに字がない(帳票出力) 外字 私用領域を使った既存資産(Windowsの外字) バッチ・シェル コンソールのコードページ(後述の CMD の話) 「アプリは Unicode になったが、周辺が追いついていない」——
というのが現在の実情である。
本ページの後半(CUI / FTP)が扱っているのは、まさにその周辺の話である。
FTP をコマンドで実行した所、文字化けしたという話がありましたが、
コマンド・プロンプト(CMD)が SJIS アプリケーションとして動作しているためです。
コマンド・プロンプト(CMD)は、
cmd /u その他コマンドライン引数で Unicode 対応します。
それ以外は SJIS です(日本のロケールでは)
#日本語以外では各国のロケールの既定の文字コード。
↓のコマンドを /u 有り・無しで起動したコマンド・プロンプト(CMD)から実行テストすると解ります。
C:\Users\daisukenishino>echo 鱓 > aa.txt鱓(ごまめ)は、Unicode にしか無い文字。
(Unicode で BOM 無しで出力されるためサクラエディタなどから開いて下さい)
移行メモ(
cmd /uの効果は限定的):/uは
「内部コマンドがパイプ・リダイレクトへ出力する際に UTF-16 で書く」
という指定であり、「CMD 全体が Unicode 対応になる」わけではない。【cmd /u が影響する範囲】 ○ echo、dir、type などの【内部コマンド】の パイプ・リダイレクト出力 → UTF-16 LE(BOM なし) ✗ 画面表示のコードページ → 変わらない(chcp のまま) ✗ 外部コマンド(ftp.exe 等)→ 影響しない ✗ 入力(コマンドライン引数)→ 影響しない原文の実験(
echo 鱓 > aa.txtが UTF-16 BOM なしで出る)は
この仕様の通りであり、観察は正確である。
ただし「FTP の文字化けが/uで直る」わけではない
(ftp.exeは外部コマンドのため)。コンソールのコードページを変えるには
chcpを使う。chcp 65001 :: UTF-8 に切り替える chcp 932 :: CP932(既定)に戻す現在の状況:
項目 現在 Windows Terminal UTF-8 で正しく動く。既定のターミナルになった PowerShell 7 既定が UTF-8(BOM なし)。CMD の制約がない Windows 10 1903 以降 「ベータ: ワールドワイド言語サポートで UTF-8 を使用」を設定するとシステム既定が UTF-8 になる .NET の Console Console.OutputEncodingで明示的に設定できる# PowerShell 7 では既定で UTF-8(BOM なし) "鱓" | Out-File aa.txt// .NET のコンソール アプリで確実に UTF-8 を出す Console.OutputEncoding = Encoding.UTF8;「ベータ: UTF-8 を使用」の設定には副作用がある点に注意する。
システムの ANSI コードページが 65001 になるため、
CP932 前提の古いアプリが軒並み文字化けする。
検証環境で確認してから有効化すること。**現在の指針は「CMD を使わない」**である。
PowerShell 7 か、
UTF-8 を明示設定した .NET コンソール アプリ
(自作CUI(CLI)の話)を使う方が確実である。
FTP は、転送モード(ascii または binary)があり、
転送モード:ascii では、自動エンコーディングするので、
文字化けが発生する場合は、設定などで回避する必要がある。
-
FFFTPで日本語ファイルが文字化けする場合の設定変更方法
http://support.clara.jp/use/web/upload/ftp/ffftp_utf8off.htm -
FileZilla Serverの設定方法
http://www.aconus.com/~oyaji/ftp/filezilla_server_conf.htm -
Windows エクスプローラーの FTP 機能を利用して日本語が含まれたファイルを
FTP サイトへアップロードすると、ファイル名が文字化けする、
もしくは FTP フォルダー エラー が発生する場合がある
http://support.microsoft.com/kb/2416991/ja
エンコーディングの指定は無いようなので、
ファイル名などの文字化けなどが発生した場合、
convmv というコマンドを使用して変換するなどが必要になる。
- Linuxでファイル名の文字コードを変換する
(文字化けを直す):while(1) { ;}:So-netブログ
http://aoi-f.blog.so-net.ne.jp/2010-09-08-1
補足(FTP の文字化けの構造と、現在の代替): FTP の文字化けには
2 つの別々の原因があり、混同されやすい。【原因① ファイルの中身】 転送モードが ascii だと、改行コードが変換される Windows: CRLF ←→ Unix: LF → バイナリ ファイルが壊れる(画像、ZIP、Excel) → 対策: binary モードで転送する 【原因② ファイル名】 FTP はファイル名の文字コードを規定していなかった サーバ: CP932 / EUC-JP / UTF-8 のどれか クライアント: 別のもの → 対策: RFC 2640(UTF-8 対応)の OPTS UTF8 ON原文の「エンコーディングの指定は無いようなので」は
RFC 2640 以前の理解である。
現在はRFC 2640 で UTF-8 が規定され、
主要なサーバ・クライアントは対応している
(FileZilla、vsftpd、IIS FTP など)。・サーバが FEAT 応答で UTF8 を返す ・クライアントが OPTS UTF8 ON を送る → 以降、ファイル名は UTF-8 でやり取りされるただし、古いサーバや、CP932 でファイル名を保存済みの環境では
依然として問題が残るため、原文のconvmvの話は今も有効である。より本質的な補足:FTP 自体を使わない
【FTP の問題】 ・【認証情報が平文で流れる】(FTPS/SFTP でなければ) ・ファイアウォール越えが面倒(PASV / PORT、データ用ポート) ・文字コードの規定が後付け ・転送の完全性を保証しない
代替 内容 SFTP(SSH File Transfer Protocol) SSH 上で動く。別プロトコル(FTP とは無関係) FTPS FTP を TLS で保護。FTP の他の問題は残る HTTPS(REST API) 最も素直。ファイアウォールを通る オブジェクト ストレージ(Azure Blob、S3) 現在の第一選択。SDK で扱える rsync / robocopy 差分転送。同一ネットワーク内向け SFTP は名前が似ているが FTP とは別物である
(FTPS と混同しないこと)。
ファイル名は UTF-8 が規定されており、この点でも優れる。【現在のシステム間ファイル連携の指針】 ① 可能なら【オブジェクト ストレージ + SDK】 ② 相手が FTP しか話せないなら【SFTP か FTPS】 ③ ファイル名は【ASCII に限定する】 → 日本語ファイル名は、連携の入口では使わない → 論理名はメタデータ(JSON、DB)側で持つ ④ 中身の文字コードは【UTF-8 + BOM の有無を明記】して合意する③ が実務的に最も効く。
ファイル名を ASCII に限れば、文字コードの問題は消える。
- Unicode と文字セットの使用(Windows アプリ)
https://learn.microsoft.com/ja-jp/windows/win32/intl/unicode - コード ページを使用したアプリのグローバル化(UTF-8 の使用)
https://learn.microsoft.com/ja-jp/windows/apps/design/globalizing/use-utf8-code-page - Console.OutputEncoding プロパティ
https://learn.microsoft.com/ja-jp/dotnet/api/system.console.outputencoding - chcp コマンド
https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/chcp
Tags: 移行, .NET開発, 国際化対応, 文字コード
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。