英語環境VBでユニコードファイルを読み込むには

解決


fuu  2004-06-24 21:25:38  No: 114278  IP: [192.*.*.*]

環境は 英語版VB5 SP3 WinNT4.0 SP5 です。

ユニコードで保存されたファイルから文字列を取得して、英語環境であれば、英語で、日本語環境であれば、日本語で文字列を表示する方法が知りたいです。
ユニコードのファイルから文字列を取得することは外せません。(Resファイルは使用できないし、アスキーコードファイルも使用不可です)

現状は
取得した文字列を strConv(文字列,vbFromUnicode)で変換して出力させようとすると、英語環境では文字化けで、日本語環境ではある特定の文字(全角、半角問わず)が文字化けします。
strConv(文字列,vbFromUnicode)を使用しないと、英語環境では正しく表示されますが、日本語環境だと文字化けです。

非常に困っています。
どうか、どなたか御教授お願いします。

編集 削除
魔界の仮面弁士  2004-06-25 00:02:24  No: 114279  IP: [192.*.*.*]

具体的には、どのUnicodeでしょうか?
一口にUnicodeといっても、いろいろな種類がありますよね。
http://homepage1.nifty.com/nomenclator/unicode/ucs_utf.htm

とりあえず、UCS-2なら、FileSystemObjectのOpenTextFileメソッドで
読み込めます。それ以外であれば、ADODB.Streamオブジェクトが
使えるでしょう。あるいは、mlang系のAPIを使うと言う手もあります。


> 取得した文字列を strConv(文字列,vbFromUnicode)で変換して出力させようとすると、
(バイト配列ではなく)文字列にできているなら、もう、StrConvの必要は無いかと。
バイト配列のままだとしたら、strConvは止めた方が良いかも知れません。
VB6と違って、第3引数の指定もありませんし。

編集 削除
魔界の仮面弁士  2004-06-25 02:54:22  No: 114280  IP: [192.*.*.*]

VB5の文字列は基本的にはUCS-2ですから、元のUnicodeデータがUCS-2なら、
文字コードの変換は不要かと思います。元がUTF-8等なら、変換が必要ですけれども。


> 英語環境であれば、英語で、日本語環境であれば、日本語で文字列を表示する方法が知りたいです。
Unicodeを読み込んだ後、それを表示させる所でつまずいているのでしょうか。

VB5では、文字列は内部的にUnicodeで保持されていますが、だからといって、
VB自体がUnicodeに完全対応しているというわけではありません。たとえば、
元のソースコード自体はANSIベースですし、LabelやTextBox等にしても、
Unicodeには対応していません。

それゆえ、システム規定のコードページに変換できない文字を渡した場合は、
コントロールとのやり取りを行う際に、データが化けてしまう事になります。


となると対処方法は2つで、「変換できない文字は諦める」か、もしくは
「Unicodeのまま表示させる事を考える」か、といった事になるでしょう。

# 英語環境で日本語を表示させる必要が無い場合は前者(または後者)で、逆に、
# 英語環境で日本語を表示させる必要があるなら、後者で対応するとか。


たとえば前者の場合、GetSystemDefaultLangID / GetSystemDefaultLCID API などで、
現在の環境が英語環境か日本語環境かを判断してやり、それに応じて、読み込むべき
Unicodeデータファイルを切り替える、といった運用ができるかと思います。

# ただし、あらかじめデータファイルを各国語別に分けておけないのでれば、
# ファイルから読みこんだ文字が日本語なのかどうかを調べる必要があるかも。


一方、後者の場合は、UCS-2形式のデータ自体を、Unicode対応の
ActiveXコントロール(たとえばWebBrowser等)に表示させるとか、あるいは、
TextOutW APIでFormやPictureBox等に出力するなどという手があります。

この場合、フォント自体がUnicodeに対応していないと、一部のグリフが
正しく表示できない可能性がありますが、もしも Office をお持ちであれば、
CD-ROM内にある「Arial Unicode MS」というフォント(ARIALUNI.TTF)を使う事で、
Unicode 2.1に収録されている文字全てを利用する事ができます。

# Arial Unicode MS は、字体があまり綺麗では無いのが難点ですが…。

編集 削除
fuu  2004-06-25 09:15:34  No: 114281  IP: [192.*.*.*]

遅くなってすみません。
もう少し、詳しく書きます。

APIのGetSystemDefaultLangIDで現在の言語環境を判断しています。
ファイルには英語と日本語の両方の文字列を用意していて、APIの判断によって、
英語の方とか日本語の方とかを選んで文字列を取得しています。

そして、この取得した文字列をexeに使用される全ての文字列に使用し、NLS化を行
おうとしています。

もう一度まとめますと、
英語環境    strConv使用     文字化け
英語環境    strConv不使用   正しく表示
日本語環境  strConv使用     特定文字が文字化け
日本語環境  strConv不使用   文字化け
といった感じです。

Lenで文字数を見てみると、例えば(英語)Close、(日本語)閉じる、を調べた時

英語環境    strConv使用    2文字(Closeeとした場合は3文字でした)
英語環境    strConv不使用  5文字
日本語環境  strConv使用    3文字
日本語環境  strConv不使用  6文字

といった感じです。

>VB5では、文字列は内部的にUnicodeで保持されていますが、だからといって、
>VB自体がUnicodeに完全対応しているというわけではありません。たとえば、
>元のソースコード自体はANSIベースですし、LabelやTextBox等にしても、
>Unicodeには対応していません。
>それゆえ、システム規定のコードページに変換できない文字を渡した場合は、
>コントロールとのやり取りを行う際に、データが化けてしまう事になります。
このあたりが、原因ではないかと思います。

それで、
「変換できない文字は諦める」
「Unicodeのまま表示させる事を考える」
のどちらかになるということですね。
ユニコードの種類に関しては知らなかったので、これから調べます。  

御教授、大変ありがとうございます。
とても、勉強になりました。

編集 削除
魔界の仮面弁士  2004-06-25 12:57:17  No: 114282  IP: [192.*.*.*]

> ユニコードの種類に関しては知らなかったので、これから調べます。  
よく使われる符号化方式は、UCS-2(UTF16相当)か、UTF-8あたりでしょうね。

前者はすべての文字が2バイトで表現されるのですが、後者(UTF-8)は、
文字によってバイト数が異なります(1〜6バイト)。
たとえば、ASCII文字(Basic Lathin)等は1バイトですが、ギリシャ文字(Greek)等は2バイト、
中国/日本/韓国語(CJK Unified Ideographs)等は3バイトで表現されます。
# ちなみに、VB.NETではUTF-8が多用されています。

> そして、この取得した文字列をexeに使用される全ての文字列に使用し、NLS化を行
> おうとしています。
質問の表題にある「Uniodeの読み込み」に関しては、そう難しい話では
無いと思っています。難しいのはむしろ、読み込んだUnicode文字列を、
どうやって VBの画面上に表示させるかという点でしょうね。


> もう一度まとめますと、
> 英語環境    strConv使用     文字化け
> 英語環境    strConv不使用   正しく表示
> 日本語環境  strConv使用     特定文字が文字化け
> 日本語環境  strConv不使用   文字化け
> といった感じです。
「文字は正しいが、グリフが異なってしまう」という状態
(例えば、http://www.ocv.ne.jp/~oratorio/junk/charcter.html)ではなく、
データそのものが化けてしまっている状態ですよね。

まず、StrConvというのは、vbFromUnicode/vbUnicodeを指定した時の事だと思いますが、
それらの定数は、Unicodeと「システム既定のコードページ」の間での変換を指示する物です。

たとえば——Shift_JISで、すべての中国語漢字を扱う事はできませんよね。
日本に無い漢字は、Unicodeでは表現できても、Shift_JISでは表せませんから。

それと同じで、英語環境で vbFromUnicode を使っても、日本語文字を
ANSI変換する事はできないわけです。それゆえ、StrConvしない方が良いでしょう。
(同様の理由で、LCMapString API をそれらの文字に使った事も避けるべきかと)

もしも、文字化けせずに表示させたいなら(つまり、化けそうな文字を切り捨てたり、
使えない文字を代替文字に置換したりする事無しに、正しく表示させたいならば)、
コードページの変換を行ってから表示するのではなく、Unicodeのまま表示させてやる
必要があるかと思います。(この場合、標準コントロールは一切使えませんが…)


> 「変換できない文字は諦める」
> 「Unicodeのまま表示させる事を考える」
> のどちらかになるということですね。
私自身は、多言語対応アプリを作った経験は無いのですが、もし実際に
作る事になったとすれば、この2つのいずれかを採用すると思います。


前者は、「日本語環境では日本語しか表示させない」のような考え方です。

たとえば、『(c)』のコピーライト文字などは、Shift_JISでは表現できませんので
(欧文フォントや記号フォントを使って、見た目上で表現するという事はできますけど)、
あらかじめ、「元のデータに、表現できない文字を含めないようにしておく」か、
もしくは、「表現できないデータが出てきたら読み捨てる」事で対処するという方法です。

一方後者は、可能な限り、「すべての環境で、すべての文字を表示させる」という考え方です。

Win9X系だと、OSのUnicodeサポートの関係から、対応できない部分もあるかも
知れませんが、NT4であれば理論的には可能だと思います。
# VB.NETのコントロールとは異なり、VB5の標準コントロールでは、
# Unicode 文字を扱えないという点がネックになりますが…。

なお、VB5/VB6にてUnicode文字を表示するサンプルは、過去に何度か
紹介していますので、掲示板の過去ログについても調べてみてください。

編集 削除
fuu  2004-06-25 13:45:46  No: 114283  IP: [192.*.*.*]

魔界の仮面弁士殿

ありがとうございます。
まだまだ、解決への道のりは長そうですが、何が問題になっているのかはなんとなく掴めた気がします。

変換できない文字はあきらめる、というのが有力そうですが。。。

初めての投稿でしたが、丁寧に御教授下さって大変感謝しています。
後は、自分で何とか調べてみます。

本当に、ありがとうございました。
また、何かあったらよろしくお願いします。

編集 削除