練炭ブログ

萌え壁紙、Irvine、DMonkey、Proxomitron などの情報を扱ってます。

DMonkey: iconv.dll による文字列変換

コメントなし»

KaoriYa さんが配布している Vim に同梱されている iconv.dll を使って、Irvine のスクリプトで UTF-8 文字列を Shift_JIS に変換するテスト。

function iconvUtf8ToSjis (text) {
	var Dorothy = { path: 'C:\bin\Irvine\Dorothy2\' };

	var dll = Dorothy.path + 'bin\iconv.dll';

	var d = new DynaCall ();
	d.register (dll, 'libiconv_open',	'i=ss',		'r=l');
	d.register (dll, 'libiconv_close',	'i=l',		'r=l');
	d.register (dll, 'libiconv',		'i=lssss',	'r=l');

	var n;

	var iconv = d.libiconv_open ('Shift_JIS//IGNORE', 'UTF-8');
	// alert ('libiconv_open: ' + iconv);

	var insb = new StringBuffer (text);
	var inbufp = new Struct ('inbuf:s');
	inbufp.inbuf = insb;

	var inbytesleftp = new Struct ('inbytesleft:l');
	inbytesleftp.inbytesleft = new Number (insb.length);

	var outsb = new StringBuffer (100);
	var outbufp = new Struct ('outbuf:s');
	outbufp.outbuf = outsb;

	var outbytesleftp = new Struct ('outbytesleft:l');
	outbytesleftp.outbytesleft = new Number (outsb.length);

	n = d.libiconv (iconv, inbufp, inbytesleftp, outbufp, outbytesleftp);
	// alert (n + "\n\n" + outbytesleftp.outbytesleft + "\n\n" + outsb.text);

	n = d.libiconv_close (iconv);
	// alert ('libiconv_close: ' + n);

	return outsb.text;
}

var t = String.fromCharCode (0x61, 0xF0, 0xA0, 0xAE, 0xB7, 0x7a);
alert (iconvUtf8ToSjis (t));

てきとうに書いたのでバッファの扱いとか間違っているかもしれません。Irvine の動作自体がおかしくなる恐れもあるので、このコードは実行しないで下さい。

変換できない文字を米印※とかゲタ〓のような任意の文字に変換できればよかったんですが、変換自体をエラーにするか文字を無視するかしか選べないようです。

YouTube でタイトルに結合文字が使われている例

コメントなし»

YouTube で動画のタイトルに、Unicode の合成済み文字ではなく結合文字が使われている例です。

UTF-8 文字列を Shift_JIS に変換するコードのテスト用とかにどうぞ。

おまけ

DMonkey: Shift_JIS → UTF-8 → Shift_JIS の変換

コメントなし»

HTML の文字参照を UTF-8 にデコードするルーチンを作っているんですが、ページの文字コードが Shift_JIS だと使えない(文字列をそのまま突っ込むと Shift_JIS と UTF-8 が混在する結果になってしまう)ので、あらかじめ UTF-8 に変換してからデコードして、その後 Shift_JIS に戻す手順ならどうだろう、という流れで変換によって文字が変わってしまうことがあるかの調査。

参考:シフトJIS / EUC-JPとUnicodeとの妥当な変換表 | Netsphere Laboratories

function p (s) {
  var t = format ("before: 0x%.4x %s", s.charCodeAt (0), s);

  var utf8 = new StringBuffer (s.toUTF8 ());
  if (0) {
    t += "\nutf8: ";
    for (var i = 0; i < utf8.length; ++i) {       t += format ('0x%.2x ', utf8.charCodeAt (i));     }   }   var sj = utf8.toString ().fromUTF8toSJIS ();   t += format ("\nafter:  0x%.4x %s", sj.charCodeAt (0), sj);   alert (t); } function c (cc) {   p (String.fromCharCode (cc)); } p ('~'); p ('~'); p ('\'); p ('\'); // NEC 特殊文字 //c (0x8790); // → 0x81e0 //c (0x8791); // → 0x81df //c (0x8792); // → 0x81e7 //c (0x8795); // → 0x81e3 //c (0x8796); // → 0x81db //c (0x8797); // → 0x81da //c (0x879a); // → 0x81e6 //c (0x879b); // → 0x81bf //c (0x879c); // → 0x81be // IBM 拡張文字 //c (0xfa4a); // → 0x8754 //c (0xfa4b); // → 0x8755 //c (0xfa4c); // → 0x8756 //c (0xfa4d); // → 0x8757 //c (0xfa4e); // → 0x8758 //c (0xfa4f); // → 0x8759 //c (0xfa50); // → 0x875a //c (0xfa51); // → 0x875b //c (0xfa52); // → 0x875c //c (0xfa53); // → 0x875d //c (0xfa54); // → 0x81ca //c (0xfa58); // → 0x878a //c (0xfa59); // → 0x8782 //c (0xfa5a); // → 0x8784 //c (0xfa5b); // → 0x81e6

NEC 特殊文字や IBM 拡張文字は JIS X 0208 へ変換されてしまいます。

むしろその方が良いかも知れませんが、入力と出力が同じ Shift_JIS なのに Shift_JIS に存在する文字が変換されてしまうのは多少気持ち悪いかも。

Shfit_JIS のままデコードする(実体参照は Unicode から Shift_JIS に変換する)ルーチンを UTF-8 用とは別に用意してみようかと思います。

U+005C がブラウザでどう表示されるか → 保存ファイル名としてどう変換するのが適切か、という点について後で調査。

縲鰀の謎

コメントなし»

ここに出てくる「縲鰀」とは波ダッシュ「〜」のことらしいです。
「縲鰀」とはどういう意味ですか? - 人力検索はてな

確かに、波ダッシュが化けていると考えると適切な文章として解釈できます。ただ、なぜ ? などではなく「縲鰀」に化けてしまうのかが謎です。

文字 文字の解説 コードポイント UTF-8
U+7E32 0xE7 0xB8 0xB2
U+9C00 0xE9 0xB0 0x80
波ダッシュ U+301C 0xE3 0x80 0x9C
全角チルダ U+FF5E 0xEF 0xBD 0x9E

文字コードから、何がどうなるとこうなる、という関連性が見当たりません。強いて言えば「鰀」の U+9C00 と波ダッシュの UTF-8 3バイト目の 0x9C が怪しい……?