UTF8→Shift-JISへの変換

オープンソース形式でコードを共有するフォーラムです。お役立ちコード、あなたも投稿してみませんか?
返信する
メッセージ
作成者
Sinryow
記事: 141
登録日時: 2005年5月31日(火) 09:34
お住まい: 北海道
連絡する:

UTF8→Shift-JISへの変換

#1 投稿記事 by Sinryow »

http://dbp.cool.ne.jp/patio/patio.cgi?mode=view&no=229 をActiveBasicに移植しました。
Shift-JIS→UTF8への変換」とセットでどうぞ。

コード: 全て選択

Declare Function WideCharToMultiByte Lib "Kernel32" (
	CodePage As Long,
	dwFlags As DWord,
	lpWideCharStr As WordPtr,
	cchWideChar As Long,
	lpMultiByteStr As BytePtr,
	cbMultiByte As Long,
	lpDefaultChar As BytePtr,
	lpUsedDefaultChar As DWordPtr
) As Long

Function UTF8toSJIS(source As BytePtr) As String
	Dim u2s As BytePtr
	Dim u2s_out As BytePtr
	Dim l As Long
	
	' UTF-8からUnicodeに変換
	l=MultiByteToWideChar(CP_UTF8, 0, source, -1, 0, 0)
	u2s_out=calloc(l*2+2)
	MultiByteToWideChar(CP_UTF8, 0, source, -1, u2s_out, l)
	
	' UnicodeからShift-JISに変換
	l=WideCharToMultiByte(CP_ACP, 0, u2s_out, -1, 0, 0, 0, 0)
	UTF8toSJIS=ZeroString(l)
	WideCharToMultiByte(CP_ACP, 0, u2s_out, -1, UTF8toSJIS, l, 0, 0)
	
	' 後始末
	free(u2s_out)
End Function
最後に編集したユーザー Sinryow [ 2005年11月04日(金) 22:48 ], 累計 1 回
' ============================================================
' Sinryow Game Home Page - http://www.sinryow.net/
' Sinryow ActiveBasic Center - http://ab.sinryow.net/
' ============================================================
マティ
記事: 161
登録日時: 2005年8月23日(火) 00:15
お住まい: 沖縄県
連絡する:

#2 投稿記事 by マティ »

質問:このままではUTF-8→UNICODE→UTF-8変換すると文字化けしませんか?
(自分の環境で問題になった件と同じ現象がでそうなので・・・)

このままUTF-8からUNICODEに変換すと・・・UNICODEの最後にNULLが付加されません。

コード: 全て選択


    ' UTF-8からUnicodeに変換
    l=MultiByteToWideChar(CP_UTF8, 0, source, -1, 0, 0)
    u2s_out=calloc(l*2)
    MultiByteToWideChar(CP_UTF8, 0, source, -1, u2s_out, l)
しかし、次の処理ではl=WideCharToMultiByteでバイト数を取得する際に、文字数を自動(-1:UNICODEの最後はNULLで終わる)に設定)しています。

コード: 全て選択


    ' UnicodeからShift-JISに変換
    l=WideCharToMultiByte(CP_ACP, 0, u2s_out, -1, 0, 0, 0, 0)
    UTF8toSJIS=ZeroString(l)
    WideCharToMultiByte(CP_ACP, 0, u2s_out, -1, UTF8toSJIS, l, 0, 0) 
つまり、NULLが2バイト連続で続く領域までが文字変換の対象になりますので、変換結果は保証されません!

PS.自分はS-JIS変換 CP_UTF8 を CP_ACP に変えて、念の為にバイト数&ワード数を指定して使用しています。

山本様

コード: 全て選択


Declare Function WideCharToMultiByte Lib "Kernel32" (
    CodePage As Long,
    dwFlags As DWord,
    lpWideCharStr As WordPtr,
    cchWideChar As Long,
    lpMultiByteStr As BytePtr,
    cbMultiByte As Long,
    lpDefaultChar As BytePtr,
    lpUsedDefaultChar As DWordPtr
) As Long 
も標準で定義出来ないでしょうか?MultiByteToWideCharは定義済み
山本
Site Admin
記事: 535
登録日時: 2005年5月30日(月) 15:08
連絡する:

#3 投稿記事 by 山本 »

マティ さんが書きました:山本様

コード: 全て選択


Declare Function WideCharToMultiByte Lib "Kernel32" (
    CodePage As Long,
    dwFlags As DWord,
    lpWideCharStr As WordPtr,
    cchWideChar As Long,
    lpMultiByteStr As BytePtr,
    cbMultiByte As Long,
    lpDefaultChar As BytePtr,
    lpUsedDefaultChar As DWordPtr
) As Long 
も標準で定義出来ないでしょうか?MultiByteToWideCharは定義済み
了解しました。次回のバージョンアップで追加しておきます。
マティ
記事: 161
登録日時: 2005年8月23日(火) 00:15
お住まい: 沖縄県
連絡する:

#4 投稿記事 by マティ »

山本様ありがとございます。
Sinryow
記事: 141
登録日時: 2005年5月31日(火) 09:34
お住まい: 北海道
連絡する:

#5 投稿記事 by Sinryow »

> このままUTF-8からUNICODEに変換すと・・・UNICODEの最後にNULLが付加されません。
> ' UTF-8からUnicodeに変換
> l=MultiByteToWideChar(CP_UTF8, 0, source, -1, 0, 0)
> u2s_out=calloc(l*2)
> MultiByteToWideChar(CP_UTF8, 0, source, -1, u2s_out, l)

「u2s_out=calloc(l*2+2)」とすれば大丈夫ですかね?
' ============================================================
' Sinryow Game Home Page - http://www.sinryow.net/
' Sinryow ActiveBasic Center - http://ab.sinryow.net/
' ============================================================
マティ
記事: 161
登録日時: 2005年8月23日(火) 00:15
お住まい: 沖縄県
連絡する:

#6 投稿記事 by マティ »

Sinryowさん返信が遅くなって申し訳ありません。
もう既に解決済みとは思いますが・・・

最後の2バイトに0を設定するとOKです!
領域を確保しただけでは、0は設定されないと思いますので、
必ずプログラムで設定してください。
hira
記事: 203
登録日時: 2005年5月31日(火) 20:14
お住まい: 兵庫県
連絡する:

#7 投稿記事 by hira »

横槍ですが…
calloc() で確保している以上、領域は0で初期化されるのではないでしょうか?
※もちろん malloc() の場合の初期値は不定ですが
マティ
記事: 161
登録日時: 2005年8月23日(火) 00:15
お住まい: 沖縄県
連絡する:

#8 投稿記事 by マティ »

hiraさま
C言語を勉強したのが10数年前なので・・・
(個人的にはもっと前ですが、その頃はallocしか無かったような・・・それよりもBASIC+アセンブラで書いた方が効率が良かったような気が・・・)

その頃、OS2用のプログラムを作成する際にC言語標準のメモリ確保(alloc,malloc,calloc)は使用禁止されていました。
確保されたメモリーがGDT,LDTのどちらに所属するのかコンパイラによって保障が出来なかったからです!
(どちらがGDTで、もう一方がLDTだったような気がします・・・)

そのためメモリー領域を取得するAPIを使用しなければならなかったので、確保できたメモリーの状態はユーザが保障する必要がありました!!!
ってな訳で最近C言語を使用していない自分は、確保した領域が絶対に安全であると保障されない場合限り、初期化をお勧めしているのです・・・

callocは確保した領域を0で初期化する事を保障しているようなので、hiraさまのご指摘通り、初期は必要ないです。
かならずプログラムで設定してください。を訂正します。
ひろ

#9 投稿記事 by ひろ »

このUTF8→Shift-JISへの変換を利用させて頂こうと思って使用した所文字化けが起こるのですが・・・^^;
ABのVerは4.24です。

解決方法を御教授願えないでしょうか?
高信期

#10 投稿記事 by 高信期 »

本当はここで答えるべきではなのですが…。

文字化けしてしまう原因は2つ、
ひとつは、UTF8(Unicode)にあってShift-JISに無い文字を変換しようとしたこと。
もうひとつは、OSがWindows95であること。

というわけで、使用しているOSと変換しようとしていた文字列を教えてください。
ひろ

#11 投稿記事 by ひろ »

> 本当はここで答えるべきではなのですが…。
すいません、、、

> ひとつは、UTF8(Unicode)にあってShift-JISに無い文字を変換しようとしたこと。
元々変換させたい文字がUTF8で無いと言うのが一番の問題かもしれません^^;

> もうひとつは、OSがWindows95であること。
OSは2000です。

>変換しようとしていた文字列を教えてください。
★変換しようとしていた文字列

変換したい文字列      変換元の文字列
文字版    ・・・譁・ュ礼沿
文字化けファイル名修正・・・譁・ュ怜喧縺代ヵ繧。繧、繝ォ蜷堺ソョ豁」

この説明をどうして良いのか不明だったのがここに書き込みさせて頂いた一番の理由です。
この意味不明な漢字をなんとか元に戻したいと思っていた所こちらのUTF8→Shift-JISを使用した際にいい所までは変換してくれるので、何とかならない物かと思いまして
konisi
記事: 893
登録日時: 2005年7月25日(月) 13:27
お住まい: 埼玉県東松山市
連絡する:

#12 投稿記事 by konisi »

変換させたい文字列がUTF-8ではないって言うのは、問題外だと思います・・・^^;
それと、Win2000は互換性の問題がかなり出ていたと思うので、そこら辺はどうなんでしょう?(調べる気にはなりませんが。)
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
返信する