あかすくぱるふぇ

同人サークル「あかすくぱるふぇ」のブログです。

2016年06月

PMX(MMDモデル)ファイルビューワーの制作で必要になったので。

PMXファイル内の文字列はUTF-8とUTF-16のどちらかで書かれている。
どちらで書かれているかはヘッダで判断できる。
つまり、ヘッダに応じて、UTF-8とUTF-16のどちらで読むかの場合分けが必要となる。

その違いを吸収するための関数を作ってみた。
typedef std::basic_string<TCHAR, std::char_traits<TCHAR>, std::allocator<TCHAR> > tstring;

tstring read(std::ifstream& fileStream, const int size)
{
tstring str;

WCHAR wcharTmp[MAX_CHAR_LENGTH];
fileStream.read(reinterpret_cast<char*>(&wcharTmp), size);

// 終端文字付きの文字列を得るためにstringを利用。
// stringは終端文字を持たない代わりに、size()関数で文字列の長さを保持する。
// そして、c_str()で終端文字付の文字列配列を返す。
std::wstring wstr = wcharTmp;
wstr.resize(size / 2);
#ifdef _UNICODE
str = wstr;
#else
char charTmp[MAX_CHAR_LENGTH];
int multiByteSize = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, wcharTmp, -1, charTmp, multiByteSize, NULL, NULL);
str = charTmp;
str.resize(multiByteSize - 1);
#endif

return str;
}
参考ページ
http://d.hatena.ne.jp/sirocco/20130418/1366253252

個人的な備忘録として。

Visual Studioでは、Unicodeとマルチバイト文字に両対応するためのTCHARという型がある。
文字列を扱う時には基本的にTCHARを使うことになるが、

"1byteずつファイルから読み込みたい"
といった場合に以下のようにしてはいけない。

TCHAR hoge;
ifs.read(hoge, sizeof(TCHAR));
こうしてしまうと、
"マルチバイト文字セットを使用する場合は1バイトずつ、Unicode文字セットを使用する場合は2バイトずつ読み込む"
といった処理になってしまう。

1バイトずつ読み込みたいなら使用文字セットに関わらず、charを使う必要がある。

↑このページのトップヘ