我在MSDN上关注如何列出目录中的文件{我正在使用当前目录)this guide。在我的情况下,我需要将信息放在我的数据包的消息部分(大小为1016的字符数组)中,以将其发送到客户端。当我在客户端和服务器上打印packet.message时,只显示文件名的第一个字符。怎么了?以下是相关代码部分的片段:
WIN32_FIND_DATA f;
HANDLE h = FindFirstFile(TEXT("./*.*"), &f);
string file;
int size_needed;
do
{
sprintf(packet.message,"%s", &f.cFileName);
//Send packet
} while(FindNextFile(h, &f));
答案 0 :(得分:5)
这通常是由于广泛的字符串被错误地视为ASCII字符串引起的。构建针对UNICODE,cFileName
包含宽字符串,但sprintf()
假设它是ASCII字符串。
FindFirstFile()
将映射到FindFirstFileA()
或FindFirstFileW()
,具体取决于构建是否针对UNICODE。
解决方案是明确使用FindFirstFileA()
和ASCII字符串。
请注意,&
:
sprintf()
sprintf(packet.message, "%s", f.cFileName);
由于应用程序正在使用超出其控制范围的字符串(即文件名),我建议使用更安全的_snprintf()
来避免缓冲区溢出:
/* From your comment on the question 'packet.message' is a 'char[1016]'
so 'sizeof()' will function correctly. */
if (_snprintf(packet.message, sizeof(packet.message), "%s", f.cFileName) > 0)
{
}
答案 1 :(得分:4)
您使用的是FindFirstFile的Unicode版本,几乎可以保证,可以调用窄版本或更改打印的格式说明符。我个人会做前者:
WIN32_FIND_DATAA f;
HANDLE h = FindFirstFileA("./*.*", &f);
string file;
int size_needed;
do
{
sprintf(packet.message,"%s", f.cFileName);
//Send packet
} while(FindNextFileA(h, &f));
FindClose(h);
或者,您可以使用MBCS或常规字符进行编译。
答案 2 :(得分:2)
正如其他人所提到的,您正在调用FindFirstFile()
的Unicode版本并将Unicode数据传递给Ansi sprintf()
函数。 %s
说明符期望Ansi输入。您可以在代码中解决此问题:
继续使用sprintf()
,但将%s
说明符更改为%ls
,以便在写入邮件缓冲区时接受Unicode输入并将其转换为Ansi:
sprintf(packet.message, "%ls", f.cFileName);
这不太理想,因为它将使用本地机器的Ansi编码,这可能与接收机器使用的Ansi编码不同。
将您的消息缓冲区更改为使用TCHAR
而不是char
,然后切换为wsprintf()
或_stprintf()
而不是sprintf()
。与FindFirstFile()
一样,它们会匹配TCHAR
和TEXT()
使用的任何字符格式:
TCHAR message[1016];
wsprintf(packet.message, TEXT("%s"), f.cFileName);
或者:
#include <tchar.h>
_TCHAR message[1016];
_stprintf(packet.message, _T("%s"), f.cFileName);
如果你必须使用char
缓冲区,那么你应该接受来自API的Unicode数据并将其转换为UTF-8进行传输,然后接收器可以将其转换回Unicode并使用它根据需要。
WIN32_FIND_DATAW f;
HANDLE h = FindFirstFileW(L"./*.*", &f);
if (h)
{
do
{
WideCharToMultiByte(CP_UTF8, 0, f.cFileName, lstrlenW(f.cFileName), packet.message, sizeof(packet.message), NULL, NULL);
//Send packet
} while(FindNextFile(h, &f));
FindClose(h);
}