C++ 使用Write成员将CString写入CFile时,每个字符后都为null

C++ 使用Write成员将CString写入CFile时,每个字符后都为null,c++,mfc,C++,Mfc,我目前正在学习MFC库CFile类,我在使用Write方法将数据写入文件时遇到了一个问题。当我将char数组作为参数传递时,它工作得非常好: char c[] = "Hello!"; int size = sizeof(c) / sizeof(c[0]); myFile.Write(c, size) 写入文件的字符: Hello! 但当我尝试将CString对象作为参数传递时: CString cS("Hello"); myFile.Write(cS, cS.GetLength());

我目前正在学习MFC库CFile类,我在使用Write方法将数据写入文件时遇到了一个问题。当我将char数组作为参数传递时,它工作得非常好:

char c[] = "Hello!"; 
int size = sizeof(c) / sizeof(c[0]);
myFile.Write(c, size)
写入文件的字符:

Hello!
但当我尝试将CString对象作为参数传递时:

CString cS("Hello");
myFile.Write(cS, cS.GetLength());
我得到:

H e l
我还尝试:

CString cS("Hello");
LPWSTR c = cS.GetBuffer();
myFile.Write(c, cS.GetLength());
cS.ReleaseBuffer();

但输出与上面相同。是什么导致了这种转变?这是因为文本存储在宽字符中吗?

这是因为您在编译时定义了
UNICODE
,而
CString
是一个宽字符字符串,每个宽字符占用两个字节。写入文件的是字符字节,后跟零字节。

这是因为编译时定义了
UNICODE
,而
CString
是一个宽字符字符串,每个字符占用两个字节。你的文件中所写的是字符字节,后面是零字节。

< P>我在MFC、Visual C++ 6到Visual C++ 2005中开发了大约4年,现在专业地支持我们的公司应用。 根据我的经验和我对
CString
类对象的了解,它们总是
NULL
终止。这可能会导致与使用字符数组不同的行为,但不是上述问题

我相信您的问题与您作为参数传递的缓冲区有关
LPWSTR
是一个32位指针,指向一个由16位字符组成的字符串

据我所知,根据您发布的内容,您正在输出16位
Unicode
字符,并将其视为
ANSI
,因此这种行为是意料之中的。如果将记事本文件作为Unicode打开,则不会看到空格


或者,如果您使用
ANSI
字符集构建项目,或者在写入文件之前将其转换为
ANSI
,则在记事本中打开输出时,空格应消失。

我一直在MFC中开发,Visual C++ 6到Visual C++ 2005大约有4年的时间,现在专业地支持我们的公司应用。 根据我的经验和我对
CString
类对象的了解,它们总是
NULL
终止。这可能会导致与使用字符数组不同的行为,但不是上述问题

我相信您的问题与您作为参数传递的缓冲区有关
LPWSTR
是一个32位指针,指向一个由16位字符组成的字符串

据我所知,根据您发布的内容,您正在输出16位
Unicode
字符,并将其视为
ANSI
,因此这种行为是意料之中的。如果将记事本文件作为Unicode打开,则不会看到空格


或者,如果您使用
ANSI
字符集构建项目,或者在写入文件之前将其转换为
ANSI
,则在记事本中打开输出时,空格应消失。

问题:

第二个参数是函数将从第一个参数(缓冲区)传输的字节数。您正在传递的是
cS.GetLength()
,它更愿意传递字符串中的字符数,而这与字符串本身可能包含的字节数不同

解决方案:

您应该将将将字符串写入文件的行更改为以下内容:

myFile.Write(LPCTSTR(cS), cS.GetLength()*sizeof(TCHAR));
CString cS(_T("Hello"));
myFile.Write(LPCTSTR(cS), cS.GetLength()*sizeof(TCHAR));
sizeof(TCHAR)
将根据您是构建Unicode还是MBCS生成不同的数字。这是因为
TCHAR
对于Unicode构建被定义为
wchar\t
,对于MBCS构建被定义为
char
。因此,无论您是否构建Unicode,将字符串的长度乘以TCHAR的大小始终等于由字符串组成的字节数

需要注意的其他要点:

你没有理由在这里调用
GetBuffer()
ReleaseBuffer()

这一点不是主要的,但是
CFile::Write
函数将
const void*
作为其第一个参数。因此,您应该将
CString
强制转换为
LPCTSTR
(如果使用Unicode或MBCS构建,则会自动计算为
LPCWSTR
LPCSTR

最后一件事:最好使用
\u T()
宏包装字符串文本,这样您就可以编译Unicode和MBCS,而无需更改代码

应用所有更改,您的整个代码将如下所示:

myFile.Write(LPCTSTR(cS), cS.GetLength()*sizeof(TCHAR));
CString cS(_T("Hello"));
myFile.Write(LPCTSTR(cS), cS.GetLength()*sizeof(TCHAR));

问题:

第二个参数是函数将从第一个参数(缓冲区)传输的字节数。您正在传递的是
cS.GetLength()
,它更愿意传递字符串中的字符数,而这与字符串本身可能包含的字节数不同

解决方案:

您应该将将将字符串写入文件的行更改为以下内容:

myFile.Write(LPCTSTR(cS), cS.GetLength()*sizeof(TCHAR));
CString cS(_T("Hello"));
myFile.Write(LPCTSTR(cS), cS.GetLength()*sizeof(TCHAR));
sizeof(TCHAR)
将根据您是构建Unicode还是MBCS生成不同的数字。这是因为
TCHAR
对于Unicode构建被定义为
wchar\t
,对于MBCS构建被定义为
char
。因此,无论您是否构建Unicode,将字符串的长度乘以TCHAR的大小始终等于由字符串组成的字节数

需要注意的其他要点:

你没有理由在这里调用
GetBuffer()
ReleaseBuffer()

这一点不是主要问题,但是
CFile::Write
函数采用
常量void*