【问题标题】:MultiByteToWideChar or WideCharToMultiByte and txt filesMultiByteToWideChar 或 WideCharToMultiByte 和 txt 文件
【发布时间】:2012-09-26 17:35:18
【问题描述】:

我正在尝试编写一个通用文本编辑器,它可以在 EditControl 中打开和显示 ANSI 和 Unicode。如果我确定文本是 ANSI,是否需要反复调用 ReadFile()?无法弄清楚如何执行此任务。我在下面的尝试不起作用,它显示“?” EditControl 中的字符。

LARGE_INTEGER fSize;
        GetFileSizeEx(hFile,&fSize);

        int bufferLen = fSize.QuadPart/sizeof(TCHAR)+1;
        TCHAR* buffer = new TCHAR[bufferLen];       
        buffer[0] = _T('\0');

        DWORD wasRead = 0;
        ReadFile(hFile,buffer,fSize.QuadPart,&wasRead,NULL);        
        buffer[wasRead/sizeof(TCHAR)] = _T('\0');

        if(!IsTextUnicode(buffer,bufferLen,NULL))
        {                       
            CHAR* ansiBuffer = new CHAR[bufferLen];
            ansiBuffer[0] = '\0';
            WideCharToMultiByte(CP_ACP,0,buffer,bufferLen,ansiBuffer,bufferLen,NULL,NULL);
            SetWindowTextA(edit,ansiBuffer);
            delete[]ansiBuffer;
        }
        else
            SetWindowText(edit,buffer);

        CloseHandle(hFile);
        delete[]buffer;

【问题讨论】:

标签: c++ file winapi


【解决方案1】:

存在一些缓冲区长度错误和异常情况,但这是您的大问题。你打电话给WideCharToMultiByte 不正确。这意味着接收 UTF-16 编码的文本作为输入。但是当IsTextUnicode 返回 false 时,这意味着缓冲区不是 UTF-16 编码的。

以下基本上是你需要的:

if(!IsTextUnicode(buffer,bufferLen*sizeof(TCHAR),NULL))
    SetWindowTextA(edit,(char*)buffer);

请注意,我已将长度参数固定为 IsTextUnicode

对于它的价值,我想我会读入char 的缓冲区。这将消除对sizeof(TCHAR) 的需求。事实上,我会完全停止使用TCHAR。这个程序应该一直是 Unicode - TCHAR 是您为 Windows 的 NT 和 9x 变体编译时使用的。我想你不再为 9x 编译了。

所以我可能会这样编码:

char* buffer = new char[filesize+2];//+2 for UTF-16 null terminator
DWORD wasRead = 0;
ReadFile(hFile, buffer, filesize, &wasRead, NULL);        
//add error checking for ReadFile, including that wasRead == filesize
buffer[filesize] = '\0';
buffer[filesize+1] = '\0';
if (IsTextUnicode(buffer, filesize, NULL))
    SetWindowText(edit, (wchar_t*)buffer);
else
    SetWindowTextA(edit, buffer);
delete[] buffer;

另请注意,此代码不允许接收 UTF-8 编码的文本。如果你想处理这个问题,你需要使用char 缓冲区并使用CP_UTF8 发送到MultiByteToWideChar

【讨论】:

  • 小心。 IsTextUnicode() can report false resultsNotepad uses IsTextUnicode() 检测文件编码,有时会出错。你不应该依赖IsTextUnicode(),也不应该对文件的编码做出假设。如果存在 BOM,它会告诉您文件的编码,因此请先查找。如果没有 BOM,请询问用户编码是什么,不要试图猜测它,因为您有时可能会猜错。
猜你喜欢
  • 2011-08-25
  • 2011-03-17
  • 2012-09-30
  • 1970-01-01
  • 1970-01-01
  • 2012-05-25
  • 2013-08-22
  • 2011-03-23
  • 2011-08-03
相关资源
最近更新 更多