情けないことに、まだ謎は解けません。

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ブログを読んでいただいてありがとうございます。

これからもよろしくお願いいたします。
X
ve 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終端が読み込まれない。

   と考えるしかないのではないでしょうか?

 

分からない...