Entry

プログラミングメモ - VC++ 9.0 の STL と Windows パス名

2009年09月13日

随分前に書こうと思ってたんですけど,忘れてたこと。

VC++ 2009 では STL 使うときに,ちゃんと設定しないと,ifstream/ ofstream 系のクラスで日本語のパスを扱えない現象があります。Windows NT 系の OS は,内部のパス文字列を Unicode(UTF-16)で管理していて,通常このパスを扱う場合,W が付いた API(CreateFileW 関数とか)を使います。ANSI 文字列(マルチバイト文字列)でパスを指定する場合は,A が付いた API(CreateFileA 関数とか)を使うんですけれど,この場合は,マルチバイト文字列を Unicode に変換して,内部で W の付いた関数を呼んでいます。

一方で,C++ の ifstream/ofstream の open() メソッド等々でパス名を指定する場合,char* 型,つまりマルチバイト文字列を指定することになります。wchar_t 型にどうやって変換しているのか謎で,実際,普通に ifstream::open() メソッドで日本語パス名を扱うことはできません。開けない。

で,この話,しばらくはまってたんですけれど,解決方法から言うと,これ,open() する前に locale::global(locale("japanese")); しないといけないんですね。cppll で解決した(参照:スレッド: [cppll:13498] ofstreamは日本語ファイル名をopenできない)。どうも,パス名の解釈で locale を見るように変更されたらしい。ML によると,open(L"foobar"); も通るみたいだけれども,これは VC++ 9.0 の独自拡張なので可搬性を確保するなら使わない方がよさげ。

もっとも,locale::global(locale("japanese")); したとしても,マルチバイト文字列(CP932)をワイド文字列に変換していることに変わりはないわけで,パフォーマンスの点から言うと,CreateFileW を直接使うのと比べて,あまり有利ではありません。また,この変換には MultiByteToWideChar という API を使うんですけれど,この API の挙動がどうにも怪しい……。できることなら直接ワイド文字列(UTF-16)を指定したいところだったりします。

どうも,Windows のシステムと STL がうまくかみ合ってない。どうにかならんもんだろうか。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN