質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • Atom (テキストエディタ)

    552questions

  • 文字コード

    214questions

    文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

Atomエディタ "〜"の扱い

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 2,024

ji6othin

score 3

・環境
Windows10
Atom(2017/01/28時点最新ver)
開発言語:php,JavaScript

・現象
Atomエディタで"〜"と書いた箇所が、
他のエディタで見ると文字化け(他の文字になる)する。

Atom → "〜"を書いて保存
秀丸で開く → "・"で表示
No editorで開く → 文字化け

逆に、
秀丸(No editor) → "〜"を書いて保存
No editor(秀丸)で開く → "〜"で表示
Atom → 文字化け

文字コード設定は全てEUC-jpになっています。
環境依存文字(①やその他特殊記号等)は性格に表示されます。

色々調べたのですが、これといった
解決策が見つからず困惑しております。

これはAtom側の仕様?バグ?なのでしょうか。
ご回答のほどよろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

まず前提知識として、次のことを知っておいてください。

  • Atom(というよりJavaScript)は文字列を全てUnicode(正確にはUTF-16)で扱っており、文字コードの選択に関わらず、エディタ上では全てUnicodeで処理している。指定の文字コードへのデコード/エンコードはファイルの読み書き時に発生する。
  • Unicodeには全角幅のチルダがU+301CとU+FF5Eの二つ存在する。(Unicode 8.0からはこの二つの文字は同じグリフになったため、同じ文字のように表示されますが、実際のコードポイントは異なります。)

Atomで書き込み時のエンコードをどこで行っているかは下記のようになっています。

  1. エディタで表示編集するファイルに対する操作はAtomのコアから切り離されて、text-bufferパッケージで行っている。
  2. text-bufferではpathwatcherのFileを使用している。
  3. pathwatechrのFileではUTF-8以外でエンコードする場合はiconv-liteを使ってエンコードしてからファイルを書き込んでいる。(UnicodeからUTF-8への変換はNode.jsに組み込まれているため、Node.jsをそのまま使用)

ファイルの読み込みも同様にiconv-liteでデコードしています。

iconv-liteが変換に使っているのがマップ表であるeucjp.jsonです。この中ではU+FF5E"a1c1""8fa2b7"二つに割り当てられていますが、U+301C〜 割り当てられていません。このため、読み込みでは

  • A1 C1 => U+FF5E
  • 8F A2 B7 => U+FF5E

となりますが、書き込みでは

  • U+301C => 3F ※ 割り当て無しのため?に変換
  • U+FF5E => 8F A2 B7 ※ A1 C1 より後のためか、エンコードはこちらが優先される。

となります。

その他、Shfit_JISおよびその亜種のCP932についてまとめると下記のようになっています。

Unicode 名称 文字 UTF-8 JIS X 0213 EUC-JP Shfit_JIS CP932
U+301C WAVE DASH E3 80 9C 1-1-33 3F(?) 3F(?) 3F(?)
U+FF5E FULLWIDTH TILDA EF BD 9E 1-2-18 8F A2 B7 81 60 81 60

※ JIS X 0213の1-2-18には通常のチルダU+007E~も割り当てられています。
※ EUC-JPは A1 C1 も読み込め、同じ 8F A2 B7 と同じU+FF5Eに変換されます。
※ 3F はASCIIの?であり、割り当て無しのための代替文字として使われています。

8F A2 B7 は何かというとJIS X 0213(JIS補助漢字)での2-23です。EUC-JPとしてはある意味正しいですが、ある意味正しくありません。なぜなら、他の実装は次のようになっているからです。

  • U+301Cを A1 C1 に割り当て、U+FF5Eは何も割り当てていない。(変換もできない)
  • EUC-JPの3バイト表記(8Fや8Eから始まる)に対応していない、または、8E(半角カタカナ)のみ対応している。そのため、8F A2 B7 は変換不可で文字化け等が起きる。

そのため、相互にEUC-JPとなった文字をやり取りするときに、おかしな動作を行います。

結論としては、iconv-liteの不具合と考えられます。しかし、チルダ問題は現状実装依存であり、これが正解という変換が存在しません。よって、現代的なプログラミングにおいては、全てをUTF-8で統一することが現実解と思われます。

それでもEUC-JPを使い続けたい場合はiconv-liteをforkして、マッピングのJSONを編集し、それを読み込むようにAtomをハックするしかないでしょう。

(iconv-liteにissue#145として投げました。修正されれば、そのうち直るかと思います。)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/29 10:42

    回答ありがとうございます。

    とても詳しい解説ありがとうございます。
    文字コードについて、もう少し勉強してみようと思います。

    ありがとうございました。

    キャンセル

  • 2017/01/29 11:28

    補足しておきますが、ざっと見たところ、iconv-liteのコード表はeucjp-msに相当するのではないかと思います (詳細に見ていないので独自の変更などもあるかもしれませんが)。少なくともプログラミングの用途のためには、eucjp-ascii相当に変えていただきたいところです。
    詳細: http://web.archive.org/web/19990203125608/http://www.opengroup.or.jp/jvc/cde/ucs-conv.html
    多くの実装では、eucjp-msかeucjp-asciiを基本に、往復変換での両者の互換性が保たれるようにしています。

    ちなみに、波ダッシュと全角チルダはグリフがそっくりでもまったく別の文字ですので、コードで分離すること自体は合理性があります (ロと口のコードが違うのと同じ)。

    キャンセル

  • 2017/01/29 13:49

    私としてはA1 C1にU+301Cを割り当てるべきところをU+FF5Eに割り当ててしまったプログラム上の不具合だと思っています。8F A2 B7にU+FF5Eを割り当てていること自体はおかしくないと思います。

    変換表は、iconv-liteの名前の通りiconvを元にしていると思われます。GNU libiconvを見る限り、A1 C1はU+301Cです。また、Shift_JISの方もlibiconvにあわせてU+FF5EではなくU+301Cを使うべきです。CP932はもともとのマップ表ではU+FF5Eですが、libiconvではU+301Cを使っている(U+FF5Eにはしないとソースのコメントに書いてある)、どうするかは微妙なところです。

    キャンセル

  • 2017/01/29 15:12

    「ロと口」は揚げ足取りっぽかったですね。すみません。
    eucjp-msはcp932との互換性を考慮したもので、公的な規格として根拠になるマッピングはありません。eucjp-ascii (JIS X 0208及びISO/IEC 646国際基準版) か、eucjp-0201 (JIS X 0208及びJIS X 0201) に準拠するのが本来だと思います (上記ページ末尾のリンク先を参照)。
    何か参考になる実装ということでは、一番信頼できるのはNKFかと思います。

    よろしくお願いします!

    キャンセル

  • 2017/01/29 16:21

    とりあえず、つたない英語でissueになげました。根拠はlibiconvにしています。
    https://github.com/ashtuchkin/iconv-lite/issues/145

    > ikedasさん
    NKFを根拠にすべきであれば、上記issueで意見していただければと思います。後はコントリビューターが判断してくれると思います。

    キャンセル

  • 2017/01/29 16:40

    了解です。ただこのほかにもマイクロソフト独自マッピングはあるので (EM DASH、DOUBLE VERTICAL LINE、MINUS SIGN、……)、まとめます。少々時間がかかります。

    キャンセル

0

結論としては、仕様だと思います。
ややこしい文字コードの問題があります。(「波ダッシュ問題」と呼ばれることもあるようです)

Unicodeには、~という文字にも「波ダッシュ」「全角チルダ」の2つの文字があります。
(フォントによっては同じ字体で表示されます)

AtomでEUC-JPとして「~」を保存すると0x8FA2B7(全角チルダ)として保存されますが、
秀丸では0xA1C1(波ダッシュ)として保存されます。

一方、秀丸では0x8FA2B7(全角チルダ)を表示できないようです。
(ちなみに、私の環境では秀丸で保存した「~」をAtomで表示できました)

EUC-JP + Atomのまま解決するのは難しいと思います。
UTF-8 + Atomにするとか、EUC-JP + 秀丸にするとかが無難かなと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/29 10:38

    回答ありがとうございます。

    どうしても現場の都合上EUC-JPで
    開発しなければならないのです…。

    全角チルダ、波ダッシュ問題は初めて聞きました。
    少し自分でも調べてみようと思います。

    ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Atom (テキストエディタ)

    552questions

  • 文字コード

    214questions

    文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。