UTF-8とShift-JIS文字コード自力変換(2004/4/24)
Windows95ではWideCharToMultiByte APIが使用出来ないため、自力で変換するためのユニットを作成しました。一応確認しましたが、バグが潜んでいるかも知れませんので、使用される方は各自で充分確認をお願いします。
Delphi 6あたりから標準でUTF-8コードを変換する関数が追加されていますが、Delphi 3〜5では使いみちがあると思います。
ソースはポインタとビット演算を多用しているため、かなり読みづらいかと思います。コード変換に興味がある方は、以下のURLを参照して下さい。
http://homepage1.nifty.com/nomenclator/unicode/ucs_utf.htm
ここから下をutftosjis.pasとして保存し、ライブラリパスの通ったフォルダに保存して下さい。尚、使用する際はUses節にutftosjisを追加してください。
(*
UTF-8 <-> SJIS 相互変換
Windows95ではWideCharToMultiByte APIが使用出来ないため、自力変換
を行なう。
コード変換はいきなりSJISに変換するよりも、一旦Unicode(USC-2)に
変換する方が楽そうだったのでそうした。
以下が参考にした貞廣知行氏のページです。感謝m(__)m
http://homepage1.nifty.com/nomenclator/unicode/ucs_utf.htm
Unicodeにしてしまえば、あとはString型に代入するだけでDelphiが自動
的にSJISにしてくれるのでとっても楽。
Copyright(c) 2004/4/24 M&I
*)
unit Utf8tosjis;
interface
uses
Windows, Sysutils;
// UTF-8(BOM付き) -> SJIS
function UTFtoSJIS(UTFStr: string): string;
// UTF-8N -> SJIS
function UTFNtoSJIS(UTFStr: string): string;
// SJIS -> UTF-8(BOM付き)
function SJIStoUTF(Str: string): string;
// SJIS -> UTF-8N
function SJIStoUTFN(Str: string): string;
implementation
// UTF-8をSJISに変換する
function UTF82Sjis(UTFStr: string): string;
var
usc2, uc: PChar;
pwc: PWideChar;
len: integer;
un: WORD;
begin
Result := '';
len := Length(UTFStr);
// 文字列の終わりを検出するために番兵4人を立てる
uc := PChar(UTFStr + #0#0#0#0);
// 安全を見て4倍のメモリを確保
usc2 := AllocMem(len * 4);
// usc2はポインタとして使うのでpwcに先頭アドレスを保存
pwc := PWideChar(usc2);
try
while uc^ <> #0 do
begin
// ASCII
if uc^ in [#0..#$7F] then
begin
usc2^ := uc^;
(usc2+1)^ := #0;
Inc(usc2, 2);
Inc(uc);
// 2byte文字その1
end else if uc^ in [#$C0.. #$DF] then
begin
un := (Ord(uc^) and $1F) shl 6 + Ord((uc+1)^) and $3F;
usc2^ := Char(Lo(un));
(usc2+1)^ := Char(Hi(un));
Inc(usc2, 2);
Inc(uc, 2);
// 2byte文字その2
end else if uc^ in [#$E0..#$EF] then
begin
un := (Ord(uc^) and $0F) shl 12 + (Ord((uc+1)^) and $3F) shl 6
+ (Ord((uc+2)^) and $3F);
usc2^ := Char(Lo(un));
(usc2+1)^ := Char(Hi(un));
Inc(usc2, 2);
Inc(uc, 3);
// 4byte文字(USC-4のみ)
end else if uc^ in [#$F0..#$F7] then
begin
un := (Ord(uc^) and $07) shl 2 + (Ord((uc+1)^) shr 4) and $03;
usc2^ := Char(Lo(un));
(usc2+1)^ := Char(Hi(un));
Inc(usc2, 2);
Inc(uc);
un := ((Ord(uc^) shl 4) and $F0) + (Ord((uc+1)^) and $3F) shl 6
+ (Ord((uc+2)^) and $3F);
usc2^ := Char(Lo(un));
(usc2+1)^ := Char(Hi(un));
Inc(usc2, 2);
Inc(uc, 3);
end else
raise Exception.Create('UTF-8 Unknown code.');
end;
// UTFから変換したUnicodeをString型で返す。これだけでSjisになっちゃう
Result := pwc;
finally
FreeMem(pwc);
end;
end;
// SJISをUTF-8に変換する
function SJIS2UTF(Str: string): string;
var
uc, sc: PChar;
usc2: PWideChar;
pw: ^Word;
//w1, w2: Word;
len: integer;
begin
Result := '';
len := Length(Str);
usc2 := AllocMem(len * 4 + 4);
pw := Pointer(usc2);
try
uc := AllocMem(len * 3 + 3);
sc := uc;
try
// 一旦Unicodeに変換
StringToWideChar(Str, usc2, len * 4);
while pw^ <> 0 do
begin
{ここはUSC-4の処理。Uninode(USC-2)では不要。ついでながら未確認。
// 00000000-000wwwxx-xxxxyyyy-yyzzzzzz
if ((pw^ and $FFE0) = 0) and ((pw2^ and $F800) <> 0) then
begin
w1 := pw^;
Inc(pw);
w2 := pw^;
Inc(pw);
// 11110www
uc^ := Char($F0 + (w2 shr 2));
Inc(uc);
// 10xxxxxx
uc^ := Char($80 + ((w2 and $03) shl 4) + (w1 shr 12));
Inc(uc);
// 10yyyyyy
uc^ := Char($80 + ((w1 shr 6) and $3F));
Inc(uc^);
// 10zzzzzz
uc^ := Char($80 + (w1 and $3F));
Inc(uc);
// 00000000-0xxxxxxx
end else }
if (pw^ and $FF80) = 0 then
begin
uc^ := Char(Lo(pw^));
Inc(uc);
Inc(pw);
// 00000xxx-xxyyyyyy
end else if (pw^ and $F800) = 0 then
begin
// 110xxxxx
uc^ := Char($C0 + (pw^ shr 6));
Inc(uc);
// 10yyyyyy
uc^ := Char($80 + (pw^ and $3F));
Inc(uc);
Inc(pw);
// xxxxyyyy-yyzzzzzz
end else begin
// 1110xxxx
uc^ := Char($E0 + (pw^ shr 12));
Inc(uc);
// 10yyyyyy
uc^ := Char($80 + ((pw^ shr 6) and $3F));
Inc(uc);
// 10zzzzzz
uc^ := Char($80 + (pw^ and $3F));
Inc(uc);
Inc(pw);
end;
end;
uc^ := #0;
Result := sc;
finally
Freemem(sc);
end;
finally
FreeMem(usc2);
end;
end;
// UTF-8(BOM付き) -> SJIS
function UTFtoSJIS(UTFStr: string): string;
begin
Delete(UTFStr, 1, 3);
Result := UTF82Sjis(UTFStr);
end;
// UTF-8N -> SJIS
function UTFNtoSJIS(UTFStr: string): string;
begin
Result := UTF82SJIS(UTFStr);
end;
// SJIS -> UTF-8(BOM付き)
function SJIStoUTF(Str: string): string;
begin
Result := #$EF#$BB#$BF + SJIS2UTF(Str);
end;
// SJIS -> UTF-8N
function SJIStoUTFN(Str: string): string;
begin
Result := SJIS2UTF(Str);
end;
end.