Записать Unicode CString в файл, используя WriteFile API - PullRequest
1 голос
/ 21 сентября 2011

Как я могу записать содержимое экземпляра CString в файл, открытый CreateFile, используя функцию WinF API API WriteFile?

Обратите внимание, что MFC не используется, а CString используется путем включения "atlstr.h"

редактировать: могу ли я сделать

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

или

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

Ответы [ 5 ]

5 голосов
/ 21 сентября 2011

С 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), которая позволяет Notepad знать, что кодировка UTF-16.

4 голосов
/ 21 сентября 2011

Вам нужно выбрать кодировку текста, преобразовать строку в эту кодировку и написать текстовый файл соответствующим образом. Простейшим является 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.

2 голосов
/ 21 сентября 2011

Преобразование в 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.

1 голос
/ 21 сентября 2011

Полагаю, вам нужен дополнительный кастинг:

WriteFile(handle, (LPCVOID)(LPCTSTR)cstr, cstr.GetLength() * sizeof(TCHAR), &dwWritten, NULL);
0 голосов
/ 21 сентября 2011

Также убедитесь, что вы пишете правильную метку порядка байтов в начале, чтобы Блокнот мог читать ее правильно.

...