質問: Win10 Pro, Python3.7です。 Shift-jisの文字(外字)を ``` "髙".encode('cp932').hex() ``` のような変換で16進数に変換したいのですが、以下サイトと一致しません。 実行結果 Python: 'eee0' サイト: FBFC PythonでもFBFCと出るようにしたいです。 ちなみに ``` "髙".encode('Shift-jis').hex() ``` だとエラーになるようです。 わかる方、よろしくお願いいたします。
回答: @Yuta Kitamuraさん回答にある紹介記事と、あと2つくらいの記事で補足すると以下になります。 髙 - ウィクショナリー日本語版 - Wiktionary 記事の下の方に-1990までのJIS X 0208系のShift JISにIBM拡張漢字として0xFBFC、NEC選定IBM拡張漢字として0xEEE0が入っていると記述されています。 Fehlersuchen und Verzeichnisse meines Windows このページで「02.05.27 はしご高」とタイトルされたパートの後半で、Windows上ではIME入力やコード変換で0xFBFCが選択されるとあります。 コードが重複している場合の動作は@Yuta Kitamuraさん2つ目の紹介記事の中に「3.「NEC選定IBM拡張文字」「IBM拡張文字」が重複する場合は、「IBM拡張文字」に統一」とあり「はしごだか」が例示されているため、0xFBFCが実情のようです。 いずれもPythonでの動作(0xEEE0になる)とは違っていますね。 シフトJIS漢字コードについての質問です。 漢字コード... このQ&A記事の回答に歴史的経緯とかがダイジェストで解説されています。 短くざっくりした内容としてならこちらでも良いかも。 試しに以下のようにPythonで「Microsoftコードページ932 - Wikipedia」の「Windows-31J に重複登録されたコード」の表を変換してみたら、**「3.「NEC選定IBM拡張文字」「IBM拡張文字」が重複する場合は、「IBM拡張文字」に統一」** という仕組みはPythonでは適用されていないようですね。全て「IBM拡張文字」ではなく「NEC選定IBM拡張文字」のコードで変換されました。何か使い方が違うのかもしれませんが。 それからそのページの「凞」「蘒」はコードが違うらしく変換出来ませんでしたので他の記事IBM拡張文字から拾って変更しました。try: except: はその名残りです。 Windows10 64bit 1909, Python 3.8.5 で試しています。 ``` extchars = list('¬∵≒≡∫√⊥∠∩∪1234567891011121314151617181920ミリキロセンチメートルグラムトンアールヘクタールリットルワットカロリードルセントパーセントミリバールページmmcmkmmgkgccm2平成〝〟KK上中下左右(有)(代)明治大正昭和∮∑∟⊿IIIIIIIVVVIVIIVIIIIXXNoTEL(株)iiiiiiivvviviiviiiixx¦'"纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑') with open('extcharscp932.txt', 'w', encoding='utf-8', newline='') as f: for c in extchars: try: s = c + ' = ' + c.encode('cp932').hex() + '\n' except: s = c + ' = utf-8 ' + c.encode('utf-8').hex() + " is can't encode to cp932\n" f.write(s) ``` ではPythonではなくMicrosoftの言語やライブラリではどうなっているか、.NET Core 3.1 C#のコンソールアプリで試すと、Wikipediaの記述のように **...「IBM拡張文字」に統一** されていました。 ``` using System; using System.IO; namespace ConsoleApp1 { class Program { static void Main(string[] args) { System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); System.Text.Encoding sjis = System.Text.Encoding.GetEncoding("shift_jis"); string extchars = "¬∵≒≡∫√⊥∠∩∪1234567891011121314151617181920ミリキロセンチメートルグラムトンアールヘクタールリットルワットカロリードルセントパーセントミリバールページmmcmkmmgkgccm2平成〝〟KK上中下左右(有)(代)明治大正昭和∮∑∟⊿IIIIIIIVVVIVIIVIIIIXXNoTEL(株)iiiiiiivvviviiviiiixx¦'"纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑"; using (StreamWriter sw = File.CreateText("extcharssjis.txt")) { foreach (char c in extchars) { sw.WriteLine(c + " = " + BitConverter.ToString(sjis.GetBytes(new char[] { c })).Replace("-", "").ToLower()); } } } } } ``` 標準機能の単純な呼び出しでは該当16進数が得られないのだから、こんな対策が考えられます。 * NEC選定IBM拡張文字の範囲(edxx - eexx)があったら、IBM拡張文字(faxx - fcxx)に変換する 単純な数値の足し引き等では駄目そうなので1対1の変換テーブルを作るとかでしょうか * Microsoftと互換のencodeを行うライブラリを探して利用する ちょっと検索した程度では見つかりませんが、どこかにはあるかもしれません * Microsoftと互換のencodeを行うライブラリを自分で作る この辺の記事が同様の問題を扱っているでしょう How do I properly create custom text codecs? Custom Python Charmap Codec