iOSに移植する必要があるWin32関数があります:
// Loads UTF-8 file and converts to a UTF-16 string
bool LoadUTF8File(char const *filename, wstring &str)
{
size_t size;
bool rc = false;
void *bytes = LoadFile(filename, &size);
if(bytes != 0)
{
int len = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)bytes, size, 0, 0);
if(len > 0)
{
str.resize(len + 1);
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)bytes, size, &str[0], len);
str[len] = '\0';
rc = true;
}
delete[] bytes;
}
return rc;
}
// LoadFile returns the loaded file as a block of memory
// There is a 3 byte BOM which MultiByteToWideChar seems to ignore
// The text in the file is encoded as UTF-8
これには、Objective C ではなく C++ を使用しており、mbstowcs と _mbstowcs_l を使用しようとしています。MultiByteToWideChar と同じようには動作しないようです。たとえば、attaché という単語の末尾にあるアクセント付きの文字は正しく変換されません (Win32 バージョンでは正しく変換されます)。標準ライブラリのどこかに「UTF-8 to UTF-16」関数はありますか?
Win32 バージョンには、私が気付いていないバグがありますか?
MultiByteToWideChar から返される長さが、mbstowcs から返される長さよりも短くなっています。
奇妙なことに、この小さなテストケースでは
char *p = "attaché";
wstring str;
size_t size = strlen(p);
setlocale(LC_ALL, "");
int len = mbstowcs(null, p, size);
if(len > 0)
{
str.resize(len + 1);
mbstowcs(&str[0], p, size);
str[len] = '\0';
}
TRACE(L"%s\n", str.c_str());
len = MultiByteToWideChar(CP_UTF8, 0, p, size, null, 0);
if(len > 0)
{
str.resize(len + 1);
MultiByteToWideChar(CP_UTF8, 0, p, size, &str[0], len);
str[len] = '\0';
}
TRACE(L"%s\n", str.c_str());
mbcstowcs から正しい出力が得られ、MultiByteToWideChar が誤って最後の文字を 65533 (REPLACEMENT_CHARACTER) に変換します。今、私は混乱しています...