情けないことに、まだ謎は解けません。
UTF-16問題の後、UTF-8(BOM付、無共に)を調べていますが、(1)のコードで、(2)のような現象が生じています。
(1)問題のコード(抜粋)
//ファイルを読み込む
BOOL bSuccess = FALSE;
HANDLE hFile = CreateFileW(FileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, NULL, NULL); //ファイルを読込みでオープン
if(hFile != INVALID_HANDLE_VALUE) { //オープンできたか
DWORD dwFileSize = GetFileSize(hFile, NULL);
if(dwFileSize != 0xFFFFFFFF) { //-1は(0xFFFFFFFF)エラー
LPBYTE Buff = new BYTE[dwFileSize](); //読み込みバッファ用ポインター
DWORD dwRead;
if(ReadFile(hFile, Buff, dwFileSize, &dwRead, NULL)) {
MessageBoxA(0, (char*)Buff, "Buff in Ascii", MB_OK); //トラップ
bSuccess = TRUE; //読み込み成功
if(Buff[0] == 0xFF && Buff[1] == 0xFE) {//UTF-16、UTF-32のBOMチェック
if(Buff[2] | Buff[3]) { //いずれもNULLではない→UTF-16のBOM
delete [] m_str; //元の文字列を廃棄して
//BOM以降の読み込んだデータを入れられるようにする
m_str = new WCHAR[(dwFileSize - 2) / sizeof(WCHAR) + 1]; //一文字多くする
CopyMemory(m_str, Buff + 2, dwFileSize - 2);
m_str[(dwFileSize - 2) / sizeof(WCHAR)] = L'\0'; //追加一文字をヌルにする
}
else { //Buff[2]とBuff[3])がいずれもNULL→UTF-32のBOM(またはUTF-16でNULLのみのファイルの場合)
bSuccess = FALSE; //UTF-32BOMの場合、何もせず読み込み失敗扱い
}
}
else if(Buff[0] == 0xEF && Buff[1] == 0xBB && Buff[2] == 0xBF) { //UTF-8のBOMチェック
dwRead = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, (LPCCH)(Buff + 3), -1, NULL, NULL);
if(dwRead) { //UTF-8文字列の場合
//m_str用メモリーの初期化
delete [] m_str;
m_str = new WCHAR[dwRead];
//UTF8をWCHARへ変換
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, (LPCCH)(Buff + 3), -1, m_str, dwRead);
}
else { //BOM付きUTF-8で変換不能な場合
bSuccess = FALSE; //何もせず読み込み失敗扱い
}
}
else { //UTF-16、32、8のBOMがない場合
//先ずBOM無しUTF-8か否かをチェック
dwRead = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, (LPCCH)Buff, -1, NULL, NULL);
if(dwRead) { //BOM無しUTF-8の場合
//m_str用メモリーの初期化
delete [] m_str;
m_str = new WCHAR[dwRead];
//UTF8をWCHARへ変換
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, (LPCCH)Buff, -1, m_str, dwRead);
}
else { //BOMが無く、UTF-8変換できない場合「丸のみ」
MessageBoxW(0, L"丸呑みします。", L"BOM無し", MB_OK); //トラップ
m_str = new WCHAR[dwFileSize / sizeof(WCHAR) + 1];
CopyMemory(m_str, Buff, dwFileSize);
//念のため、バッファの終端にNULLを置く
m_str[dwFileSize / sizeof(WCHAR)] = L'\0';
}
}
}
delete [] Buff; //読み込みバッファ解放
}
CloseHandle(hFile); //ファイルのクローズ
}
注:いずれは「丸のみ」をSJISくらいは入れてみるつもりですが、今はそれどころではないので。
(2)UTF-8のサンプル(BOM付、無し共に短、長の2種類)で試験した際の現象
(サンプルは最後に"(改行)X"(0DH、0AH、58H、00H)が入り、以下①~のシーケンスを連続して試験実施)
①UTF-8BOM付のサンプル(短、長の2種類)の読み込み
→想定通りの正常動作
②UTF-8BOM無のサンプル(短)の読み込み
→どういう訳か、MultiByteToWideCharで変換できず「丸呑みします」と表示され、文字化けする。(上記①の代わりにBOM無サンプルを読み込むと正常に読み込め、表示される。)
③UTF-8BOM無のサンプル(長)の読み込み
→想定通りの正常動作
④再度UTF-8BOM無のサンプル(短)の読み込み
→今度はサンプルが変換されて、表示されるが、次のようにサンプル(長)のデータがごみとなって残る。
BCCForm and BCCSkeltonブログを読んでいただいてありがとうございます。
これからもよろしくお願いいたします。
X have become 20 years of age and I will yet keep doing my best.
X(赤字部分がごみ)
⑤再度UTF-8BOM付のサンプル(短)の読み込み
→同様に次のようにサンプル(長)のデータがごみとなって残るが、3文字(Xの後のスペース)減少しているのは、UTF-8のBOMが3文字だからかと考えられる。
BCCForm and BCCSkeltonブログを読んでいただいてありがとうございます。
これからもよろしくお願いいたします。
Xve become 20 years of age and I will yet keep doing my best.
X
⑥再度UTF-8BOM無のサンプル(短)の読み込み
→"(改行)X"がごみとなって残るのは、UTF-8のBOM3文字(OD、OAとX)の差かと考えられる。
BCCForm and BCCSkeltonブログを読んでいただいてありがとうございます。
これからもよろしくお願いいたします。
X
X
以上ですが、
(ア)ファイルデータはサクラエディターで作成、DumpでNULL終端付きで保存されていることを確認済。
(イ)Buffは毎回動的にメモリーを確保しているし、ファイルデータ(文字列)の最後にはNULL終端が付いている。
(ウ)にもかかわらず、↑の現象が発生することを考えると、
(i) ファイルデータがBuffに読み込まれた段階でごみ問題が発生しており、
(ii) Buffが同じアドレスで生成され、ReadFile関数でファイルデータのNULL終端が読み込まれない。
と考えるしかないのではないでしょうか?
分からない...