【问题标题】:Write a unicode CString to a file using WriteFile API使用 WriteFile API 将 unicode CString 写入文件
【发布时间】:2011-11-21 19:33:14
【问题描述】:

如何将 CString 实例的内容写入 CreateFile 使用 WriteFile Win32 API 函数打开的文件?

请注意不使用MFC,通过包含“atlstr.h”使用CString

编辑:我可以这样做吗

WriteFile(handle, cstr, cstr.GetLength(), &dwWritten, NULL); 

WriteFile(handle, cstr, cstr.GetLength() * sizeof(TCHAR), &dwWritten, NULL); 

?

【问题讨论】:

  • 文本文件有一个规范。您想要哪种格式的结果文件?谁将使用该文件?您可能不应该将 TCHAR 写入文件;你应该明确编码(UTF-16,UTF-8,ANSI,...)。
  • 我将使用记事本读取文件。格式?只是一些一行接一行。无论项目的编码如何,我都希望能够在记事本中打开文件。是不可能还是我可以?
  • 你想使用什么编码? UTF16? UTF8? ANSI?

标签: winapi atl cstring writefile


【解决方案1】:

使用 ATL 是这样的:

CString sValue;
CStringW sValueW(sValue); // NOTE: CT2CW() can be used instead

CAtlFile File;
ATLENSURE_SUCCEEDED(File.Create(sPath, GENERIC_WRITE, ...));
static const BYTE g_pnByteOrderMark[] = { 0xFF, 0xFE }; // UTF-16, Little Endian
ATLENSURE_SUCCEEDED(File.Write(g_pnByteOrderMark, sizeof g_pnByteOrderMark));
ATLENSURE_SUCCEEDED(File.Write(sValueW, (DWORD) (sValueW.GetLength() * sizeof (WCHAR))));

它是字节顺序标记 (BOM),它让记事本知道编码是 UTF-16。

【讨论】:

    【解决方案2】:

    您需要选择一种文本编码,将字符串转换为该编码,然后相应地写入文本文件。最简单的是 ANSI,所以基本上你会使用 T2CA 宏将你的 TCHAR 字符串转换为 ansi,然后将内容转储到文件中。类似(未经测试/编译):

    // assumes handle is already opened in an empty new file
    void DumpToANSIFile(const CString& str, HANDLE hFile)
    {
        USES_CONVERSION;
        PCSTR ansi = T2CA(str);
        DWORD dwWritten;
        WriteFile(hFile, ansi, strlen(ansi) * sizeof(ansi[0]), &dwWritten, NULL);
    }               
    

    因为它是 ANSI 编码,所以只能在具有相同代码页设置的计算机上读取。如需更便携的解决方案,请使用 UTF-8 或 UTF-16。

    【讨论】:

      【解决方案3】:

      转换为 ANSI 会导致代码页出现问题,因此在许多情况下是不可接受的。这是一个将 unicode 字符串保存到 unicode 文本文件的函数:

      void WriteUnicodeStringToFile(const CString& str, LPCWSTR FileName)
      {
      HANDLE f = CreateFileW(FileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
      if (f == INVALID_HANDLE_VALUE) return; //failed
      DWORD wr;
      unsigned char Header[2]; //unicode text file header
      Header[0] = 0xFF;
      Header[1] = 0xFE;
      WriteFile(f, Header, 2, &wr, NULL);
      WriteFile(f, (LPCTSTR)str, str.GetLength() * 2, &wr, NULL); 
      CloseHandle(f);
      }
      

      使用:

      CString str = L"This is a sample unicode string";
      WriteUnicodeStringToFile(str, L"c:\\Sample.txt");
      

      记事本理解 unicode 文本文件。

      【讨论】:

        【解决方案4】:

        我相信您需要额外的演员表:

        WriteFile(handle, (LPCVOID)(LPCTSTR)cstr, cstr.GetLength() * sizeof(TCHAR), &dwWritten, NULL);

        【讨论】:

        • 1) 如果您必须在回答中加上“我相信”,最好不要回答。 2) 永远不要转换为 void*
        • @tenfour:好的,我敢肯定,不仅仅是相信。关于强制转换为 void* - 这是 WriteFile 参数类型。我相信你的帖子没有建设性......
        【解决方案5】:

        还要确保在开头写正确的字节顺序标记,以便记事本可以正确读取。

        【讨论】:

          猜你喜欢
          • 2013-12-09
          • 1970-01-01
          • 1970-01-01
          • 2023-03-23
          • 2016-09-28
          • 2018-01-28
          • 2020-07-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多