IEやExcel向けにUTF8⇒SJIS変換を行う
ダウンロードファイルに日本語を使用する場合、IE だと文字化けする現象に悩まされることが多いと思います。
これは、IE がダウンロードファイル名に SJIS(WIndows-31J)を基本的に要求するためです。
(正確には、OS の言語設定のデフォルトコードページ、だったかも。日本語だと CP932 ですが、他の言語だとまた違うと思います)
なので多くの方は IE 向けに SJIS に文字エンコーディング変換を行うか、URL エンコードしていると思います。
MS の KB にも下記のように言及されています。
http://support.microsoft.com/kb/436616
IE9 からはダウンロードファイル名を UTF-8 として扱う(SJIS でも正常に扱える)ので、この問題に頭を悩ませる機会は今後減りそうですね。
一方、表題の Excel は基本的に SJIS オンリーで、UTF-8 を簡単には扱えません。
CSV ダウンロード ⇒ ダブルクリックで開く ⇒ CSV に関連づけられたエクセルが起動して開く ⇒ 文字化け ってコンボは当分続きそうです。
一応 UTF-8 を BOM 付きにすれば Windows 版エクセルでは正常に閲覧できるようになりますが、Mac 版では文字化けしたままとか手焼かせやがってコノヤロ的な感じです。
IE8 もエクセルもまだまだ相手にする必要があるので、このようなコードを組みました。
# IEのダウンロードファイル名の文字化け対応
def filename_for_download(filename)
if request.env['HTTP_USER_AGENT'] =~ %r{MSIE} && request.env['HTTP_ACCEPT_LANGUAGE'] =~ /^ja/
filename = Utf8ToWin31jCodeConverter.convert_to_windows31j(filename)
end
filename
end
class Utf8ToWin31jCodeConverter
class << self
def convert_table
[
%w|301C FF5E|, # WAVE DASH => FULLWIDTH TILDE
%w|2212 FF0D|, # MINUS SIGN => FULLWIDTH HYPHEN-MINUS
%w|00A2 FFE0|, # CENT SIGN => FULLWIDTH CENT SIGN
%w|00A3 FFE1|, # POUND SIGN => FULLWIDTH POUND SIGN
%w|00AC FFE2|, # NOT SIGN => FULLWIDTH NOT SIGN
%w|2014 2015|, # EM DASH => HORIZONTAL BAR
%w|2016 2225|, # DOUBLE VERTICAL LINE => PARALLEL TO
]
end
def convert_to_windows31j(utf_8_str)
utf_8_str.encode!("UTF-8-MAC", "UTF-8", :invalid => :replace, :undef => :replace, :replace => '')
utf_8_str.encode!("UTF-8")
utf_to_win31j_safe_str = Utf8ToWin31jCodeConverter.convert(utf_8_str)
utf_to_win31j_safe_str.encode 'WINDOWS-31J'
end
def convert(str)
result = str.dup
convert_table.each do |arr|
from = code_point_to_char(arr[0])
to = code_point_to_char(arr[1])
result = result.gsub(from, to)
end
result
end
def code_point_to_char(code_point)
code_point.to_i(16).chr("UTF-8")
end
def char_to_code_point(char)
char[0].unpack("U*").first.to_s(16).upcase
end
end
end
肝になるのは二点。
convert_table メソッドの変換テーブルがないと、SJIS 変換に失敗します。
詳細は以下のサイトを参照していただくと理解しやすいと思います(コード書くときにも参考にさせていただいています)。
http://esoz.blog.fc2.com/blog-entry-59.html
http://space.geocities.jp/nequomame/java/mojibake/mojibake_01.html
もうひとつは convert_to_windows31j メソッドの最初の二行で、これがないと SJIS 変換に失敗する場合があります。
再現する環境は限定的なので、なくても正常なことが多いと思いますが。
原因は UTF-8 の NFC と NFD の違いによるものです。
こちらのサイトをご覧いただくと分かりやすいと思います。
http://d.hatena.ne.jp/zariganitosh/20131124/utf8_nfd_nfc_bom
http://sho.tdiary.net/20110204.html
※ 後者のirbでの文字エンコーディング確認操作はとても分かりやすいです。時間があればぜひ試してみてください。
例えば「あさがお」という日本語ファイル名の場合、内部的には「あさか゛お」と、濁点が一文字として記録されているんですね。
なんか半角カナみたいですけれど。
これを SJIS 変換しようとした場合、濁点に対応した文字が存在しないため、例外が発生する訳です。
通常であればこの仕様を意識する必要はあまりない(ブラウザがなんとかしてくれる)と思うのですが、FireFox でアップロードされたファイルのファイル名を SJIS 変換する場合、この UTF-8-MAC の問題が顕在化します。
Job-Hub ではユーザがアップロードしたファイルを別のユーザがダウンロードして閲覧する機能があるのですが、上記が原因で例外が発生していました。
Mac 環境の Safari や Chrome でアップロードしたファイルであれば問題ないのですが、FireFox でアップロードした日本語ファイル名のファイルの場合は顕在化します。
前者二つは NFC に変換してアップロードする仕組みで、FireFoxはNFDのままアップロードするのでしょうか。
アップロード側が Mac 版 FireFox、ダウンロード側が IE って組み合わせでしか起きないので、発生するのは結構レアかもしれません。
実際のところこの UTF-8 ⇒ SJIS 変換処理自体はもう1年近く前に実装していて、NFD の問題が発生したのはつい最近のことです。
文字コードっていろいろ難しいですね。
※ 追試が十分ではないので再現条件は間違っていたり不十分だったりするかもしれません。お気づきの方は教えてください。
Author And Source
この問題について(IEやExcel向けにUTF8⇒SJIS変換を行う), 我々は、より多くの情報をここで見つけました https://qiita.com/Oakbow/items/a62d1de9c62ee8fa2eb2著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .