くりーむわーかー

プログラムとか。作ってて ・試しててハマった事など。誰かのお役に立てば幸いかと。 その他、いろいろエトセトラ。。。

外字

MySQL(MariaDB)とPostgreSQLで文字コード指定で文字を作る(外字とか)

なんか久しぶりに書く気がする。

タイトル通り。サロゲとか外字の文字を文字コード指定でDBに入れたい時用。

MySQL(MariaDB)

insert testchar values ('外字',CHAR(0xEE8080 USING utf8mb4));
insert testchar values ('サロゲ',CHAR(0xF0A08083 USING utf8mb4));

サロゲを表現する場合、普通にIMEとかで見ると、「0xD840 , 0xDC03」って見えるけどこれを合わせた形式にする。

SELECT HEX(CONVERT(CHAR(0xD840DC03 USING utf16) USING utf8mb4));

上で出てきたコードをchar()に指定すればサロゲ文字が出る。あと、エンコード指定でutf8mb4を指定しないとダメ。サロゲ対応用の文字コードらし。

PostgreSQL

insert into testchar values('外字',chr('xE000' :: bit(16) :: int));
insert into testchar values('サロゲ','𠀃');--文字コード指定がわからん。

サロゲの文字コード指定が分かりませんでした。ごめんなさい。今度調べよ。

文字が割り当てられている外字かどうかを判定する

外字かどうかを判定するというのは結構ある。まー文字のコード範囲がE000~F8FFかどうか見ればいいだけなので、割とすぐ実装できるし、調べればすぐ出てくる。

問題は、文字が割り当てられている外字かどうかを判定しようとしたとき。割り当てられてない文字なんか入ってくるわけないと思いたくなりますが、問題はデータ移行の時。

旧システム、特に他ベンダーから移行するとか、ホストから移行するみたいな場合、外字が入ってるともー発狂したくなる状況に陥りがち。

だいたい、コードの変換表とか作ったりして対応していくと思いますが、それでも変換が間違っていたり色々問題は出てくる。そーゆー時に、外字領域のコードなんだけど、字に割当たってないコードが来た時にどう見つけるかという事です。

字に割当たっていない時は外字のフォントファイルの作られ方によると思うけど、だいたい「・」になる。場合によっては「 」空白だったり、「□」だったりする。字は全部同じ形になるけど、コード的には全部違うので、例えば「”字”=”字”」みたいな比較は不可能。

文字コードで比較できないなら、変換後の字形を比較するしかない。

とゆーことで色々試した結果、↓のコードが出来上がりましたとさ。

とりあえず割り当てられてない文字コードを指定して一文字画像として描画する。あとは調べたいデータの文字を一文字ずつ画像に描画して、画像同士を比較する。比較には画像のハッシュを計算して、それを比較する方法を使用。

とりあえず、比較のベースにする1文字を画像として描画してハッシュを取得。

Encoding unicode = Encoding.GetEncoding("UTF-16");
//比較のベースにする文字コード
short baseChar = Convert.ToInt16("E123", 16);
byte[] baseCharByte = BitConverter.GetBytes(baseChar);
//UTF-16で文字に変える
string baseCharStr = unicode.GetString(baseCharByte);

Font fnt = new Font("MS 明朝", 11);
Bitmap canvasBaseChar = new Bitmap(20, 20);//画像のサイズ
Graphics g = Graphics.FromImage(canvasBaseChar);
g.FillRectangle(Brushes.White, 0, 0, canvasSize, canvasSize);//白で塗りつぶしておく
g.DrawString(baseCharStr, fnt, Brushes.Black, 0, 0);//文字を描画
g.Dispose();

//ベースの文字画像のMD5を取得
BitmapData bmpdata = canvasBaseChar.LockBits(new Rectangle(0, 0, canvasBaseChar.Width, canvasBaseChar.Height), ImageLockMode.ReadWrite, canvasBaseChar.PixelFormat);
IntPtr ptr = bmpdata.Scan0;
int bytes = bmpdata.Stride * canvasBaseChar.Height;
byte[] rgbValues = new byte[bytes];
Marshal.Copy(ptr, rgbValues, 0, bytes);
byte[] baseHash = new MD5CryptoServiceProvider().ComputeHash(rgbValues);

あとはデータの文字列を一文字ずつ同じように画像にしてハッシュを計算してベースと比較する。

Bitmap compareCanvas = new Bitmap(20, 20);
Graphics g = Graphics.FromImage(compareCanvas);
g.FillRectangle(Brushes.White, 0, 0, 20, 20);
g.DrawString(pStr, fnt, Brushes.Black, 0, 0);
g.Dispose();

BitmapData bmpdata = compareCanvas.LockBits(new Rectangle(0, 0, compareCanvas.Width, compareCanvas.Height), ImageLockMode.ReadWrite, compareCanvas.PixelFormat);
IntPtr ptr = bmpdata.Scan0;
int bytes2 = bmpdata.Stride * compareCanvas.Height;
byte[] rgbValues2 = new byte[bytes2];
Marshal.Copy(ptr, rgbValues2, 0, bytes2);
byte[] hash2 = new MD5CryptoServiceProvider().ComputeHash(rgbValues2);

bool bEqual = false;
if (hash2 != null && hash2.Length == baseHash.Length)
{
    int i = 0;
    while ((i < hash2.Length) && (hash2[i] == baseHash[i]))
    {
        i += 1;
    }
    if (i == hash2.Length)
    {
        bEqual = true;
    }
}
if (!bEqual)
{
    Console.WriteLine("違う字形");
}
else
{
    Console.WriteLine("同じ字形");
}

画像のハッシュを計算して比較するロジックはココのブログのロジックを使わせてもらいました。

C#でutf-16の外字領域の文字があるか調べる

最近、文字コードで色々あった。とりあえず外字。utf-16の文字列内にUnicodeの私用領域の文字が含まれているか調べる正規表現。

public void hoge(string wkStr)
{
	string regexp = @"[\uE000-\uF8FF]";
	if(System.Text.RegularExpressions.Regex.IsMatch(wkStr,reqexp))
	{
	     Console.WriteLine("外字");
	}
}

そーいえば、バイナリエディタで見るとバイトの並びって逆になるのだろうか。いまいち分かってない。 エディタにもよるのかしら。

Bzで見ると「E0 00 F8 FF」⇒「00 E0 FF F8」で見える。

IISでWOFFが404になる

Webシステムで外字をWebフォント使って表示させるのを試してみたかっただけど、 CSSで指定しても全く反映されなかった。CSSは↓の感じ。

@font-face {
    font-family: 'EUDC';
    src: url('../fonts/EUDC.woff') format('woff');
}
.gaiziText{
    font-family: "EUDC";
}

ブラウザの開発者ツール使ってみると、フォントファイルをGETしてるところが404になってる。URLは正しい。どうにもわからなかったけど、調べてみるとIISのMIMEにWOFFが入って無くて404になってるらしい。

IISで↓の感じで追加してあげる。

01

02

03

追加するのは↓

拡張子: .woff
MIMEの種類: application/x-font-woff

IISによっては、「.woff」が入ってることもある。ただ、その場合、MIMEの種類が「application/x-woff」になってた。この場合、Chromeで有効にならないっぽい。なので、MIMEの種類は「application/x-font-woff」にしておかないとダメみたい。

IE9とChromeとFireFoxで↑の指定でうまく見れた。

参考にしたのはココ

問合せ