使用 WriteFile API 将 unicode CString 写入文件

Posted

技术标签:

【中文标题】使用 WriteFile API 将 unicode CString 写入文件【英文标题】:Write a unicode CString to a file using WriteFile API 【发布时间】: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? 【参考方案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】:

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

【讨论】:

以上是关于使用 WriteFile API 将 unicode CString 写入文件的主要内容,如果未能解决你的问题,请参考以下文章

WriteFile() API 钩取

win32 api CreateFile 和 WriteFile 问题

Windows API一日一练(54)WriteFile和ReadFile函数

cvi中writefile函数怎么使用

是否可以调用 WriteFile 并且应用程序将永远等待回调?

golang ioutil.WriteFile函数perm参数的用法