本気で対応するのであればCentOS側のプログラムでSJIS-UTF8の変換をすべきなのですが、今回は期間限定お試しのため、安易にCentOS側のロケールをSJISにすることにした…のですが、CentOSってデフォルトではSJISロケール入ってないんですね。(今さら知りました…)
と言うことで、SJISロケールの追加方法。
localedef -f SHIFT_JIS -i ja_JP ja_JP.SJIS
これだけでOK。
コマンド実行時に、日本語ロケールだと
キャラクタマップ `SHIFT_JIS' は ASCII 互換ではありません, ロケールは ISO C に従っていません
また英語ロケールだと
character map `SHIFT_JIS’ is not ASCII compatible, locale not ISO C compliant
という警告が出ますが、気にしなくて大丈夫のようです。
私はファイルの編集にviを使うので、viでもSJISを扱えるように.exrcに以下の1行を追加します。
set fileencodings=utf8,cp932,latin
以下のサイトを参考にさせていただきました。(ありがとうございます!)
SJIS ロケールの追加 - kamata-net.com
http://blog.kamata-net.com/archives/000076.html
CentOSのlocaleにSJISを追加 - 脳ログ - livedoor Wiki(ウィキ)
http://wiki.livedoor.jp/yoko00068/d/CentOS%A4%CElocale%A4%CBSJIS%A4%F2%C4%C9%B2%C3
ずんWiki - vim
http://www.kawaz.jp/pukiwiki/?vim
Linuxで使用されているOSSの場合、ソフト毎に独自にマルチバイト対応していたりするので、glibc で SJISロケール対応してもSJISを正しく使えないツールがあると思います。
どういった場合に、glibc で SJISロケール対応するだけで良いのか気になっています。
今回はちょっと事情が特殊で、
・研修の課題(出題側です)なので出来るだけ単純な作りにしたい
・使用する通信ミドル、DBMSともにSJIS利用に問題なし
・Linux側は数本のプログラム(研修課題)を作るだけ
という状況だったので、安易にLinux側のロケールをSJISにすることで対応しました。もっと恒久的に動かす仕組みで、開発時間がきちんと取れるのであればLinux側はUTF8で扱いたいのですが…。
ちなみに私はUNIXでのシステム開発に一番関わっていたのがAIX 4.3.3の時代なので、ロケールをSJISにすることにはそれほど抵抗がなかったりします。それでも、完全にSJISロケールでLinuxサーバを動かす事にはさすがに抵抗がありますが。(上記の環境も、SJISロケールにしているのは開発用ユーザのログインシェルだけで、システム全体はUTF8で動かしています)
SJISを利用できるものだけを利用しているという事ですね。具体的なケースを教えていただき少しですがLinuxでのSJISの利用のされかたが理解できるようになってきました。
ちなみに、プログラミング言語は Java でしょうか?
よろしくお願いいたします。
言語はWindows側がC++(VC++2010)、サーバ側がC(gcc)です。
Javaだと内部的な文字コードはプラットフォームに関わらずUTFだった気がするのですが、どうでしたっけ?
あと、mbstowcs(3) でワイド文字に変換して扱う際には、glibc の sjis では変換でいわゆる機種依存文字が変換できませんね。それに半角の \ (0x5C) が U+00A5 に変換されてしまうのでトラブルの元になります。
詳しく検証はしていせんが、localedef を次のようにした方が良いかもしれません。
# localedef -f WINDOWS-31J -i ja_JP ja_JP.SJIS
JavaはUnicodeで処理しますがソースコードをSJISとかで書くことができたような。
おぉぉ、0x5Cを含むダブルバイト文字ってgccのオプションでちゃんと解釈できるんですね。前述のAIX4.3.3時代にこの問題にはよく悩まされ、仕方がないのでダメ字(0x5Cの含まれる文字をそう呼んでいましたw)のリストを手元に置き、使いたいときには明示的にエスケープして(「画面に表\示」という感じで)対応してました。積年の課題が1つ解決してすっきりしました。ありがとうございます!
localedef -f WINDOWS-31Jも試してみたのですが、こちらはvi(vim)上で文字化けが起きるようになってしまいました。テキスト自体もさることながら、vi自身の表示(ステータスとか)も化けてしまったところを見ると、エンコーディング云々の問題ではないようです。vi自身の問題か、Teraterm側の問題か、それとも何か設定が足りていないのか。
ありがとうございました!
if v:lang =~ "^ja_JP.SJIS"
set encoding=cp932
set fileencodings=cp932
endif
これでダメなら、vim のソースコードをみて直してしまった方がはやいかもしれません。
あと文字コードの自動判定は、原理的に文字コードの判定ミスを防ぐことは不可能ですから、どういうケースで判定ミスをするのか理解していない場合は、使うべきではないでしょう。
vim で、
set fileencodings=utf8,cp932,latin
という設定をした場合、ASCIIだけのテキストを開くとutf8のファイルとして確定してしまうため、日本語を追加して保存すると utf8 で保存されるという問題もありますね。
新規作成の時の文字コードは考えていませんでした。今回は基本的にSJIS(CP932)しか使わないつもりなので、
set fileencodings=cp932,utf8,latin
とした方が良さそうですね。いっそutf8は抜いてしまってもよいかも。
ありがとうございました。
あと vim は localedef -f SHIFT_JIS -i ja_JP ja_JP.SJIS の設定の時には LANG=ja_JP.SJIS で、内部エンコーディングを sjis に設定してしまいます。内部エンコーディングが sjis だと utf8 などへの文字コード変換で \ が U+00A5 に変換されるという問題が発生してしまいます。
この問題を回避するためにも set encoding=cp932 という設定が必要になってきます。ちなみに fencodings の設定ではないので注意してください。
LinuxでのSJISロケールは、こういう問題をきちんと理解して使うべきもので手間を省きたいということで安易に使うべきではないと考えています。
encoding=cp932を設定することで正常に動作することを確認いたしました。
本件以前のコメントでご指摘いただいているにもかかわらず、encodingをfileencodingと勘違いして設定をしておりました。申し訳ございません。
べき論として、SJISロケールを安易に使うべきではないというのはその通りだと思うのですが、今回は研修の課題という本来の目的に出来るだけ集中できるよう、文字コードに関しては(今回の環境で)最も取り扱いやすいSJIS(cp932)に統一して使うつもりです。
ご指導ありがとうございました。