使用 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 写入文件的主要内容,如果未能解决你的问题,请参考以下文章
win32 api CreateFile 和 WriteFile 问题
Windows API一日一练(54)WriteFile和ReadFile函数