FindFirstFile 函數要注意多字節字符問題

本來想搞搞FindFirstFile 函數的,寫個代碼把指定目錄下的文件和屬性都打印出來,之後就是錯誤不斷。。。。

唉唉 先是FindFirsFile函數死命的報INVALID_HANDLE_VALUE錯誤,試了"e:"、"e:\\*.*"、"e:\\"等等都不行,後來乾脆把路徑改成“*”,突然發現不報INVALID_HANDLE_VALUE了,瞬間好開心啊~~  沒想到接着問題又來。。。

typedef struct _WIN32_FIND_DATA {
  DWORD    dwFileAttributes;
  FILETIME ftCreationTime;
  FILETIME ftLastAccessTime;
  FILETIME ftLastWriteTime;
  DWORD    nFileSizeHigh;
  DWORD    nFileSizeLow;
  DWORD    dwReserved0;
  DWORD    dwReserved1;
  TCHAR    cFileName[MAX_PATH];
  TCHAR    cAlternateFileName[14];
} WIN32_FIND_DATA, *PWIN32_FIND_DATA, *LPWIN32_FIND_DATA;

這是微軟給的 WIN32_FIND_DATA結構,發現打印cFileName的時候,不管是printf還是puts還是std::cout都只能打印第一個字母。。坑爹啊!!!

先把代碼貼上,唉。。人懶,代碼修修改改的挺爛的,將就着看吧

WIN32_FIND_DATA fileData;
	HANDLE fFind;
	LPSYSTEMTIME sTime = new SYSTEMTIME;
	fFind = FindFirstFile(path,&fileData);
	if(fFind == INVALID_HANDLE_VALUE) 
	{
		printf("can't find :%s\n",path);
		std::cout << GetLastError() << "\n";
		return false;
	}
	printf("max_path = %d\n",MAX_PATH);
	do {
		if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
		{
			if(strcmp((const char*)fileData.cFileName,".") && strcmp((const char *)fileData.cFileName,"..")) 
			{
				FileTimeToSystemTime(&fileData.ftCreationTime,sTime);
				printf("is dir:%s,time :%d-%d-%d\n",fileData.cFileName,sTime->wYear,sTime->wMonth,sTime->wDay);
			}
		} else 
		{
			FileTimeToSystemTime(&fileData.ftCreationTime,sTime);
			std::string fname((char *)fileData.cFileName);
			printf_s("%s ,time :%d-%d-%d\n",fileData.cFileName,sTime->wYear,sTime->wMonth,sTime->wDay);
		}
		//std::cout << fileData.cFileName << "\n";
		//puts((char *)fileData.cFileName);
		int i = 0;
#if 0
		printf("name :");
		while ((fileData.cFileName)[i] != '\0')
		{
			putchar((fileData.cFileName)[i]);
			if (i > 20)
				break;
			i++;
		}
		printf(" i  = %d" ,i);
		putchar('\n');
#endif
	}while (FindNextFile(fFind,&fileData));

	return true;
代碼上的強瘡百孔基本上展現了一路不堪的掙扎的過程,最後直接說正題,這到底是怎麼回事呢。

谷歌了一堆之後,發現原來windows這麼坑爹。。一個char型 搞出TCHAR、WCHAR、wchar_t等一大堆類型。。不管了,這些我也沒搞清楚,反正大概就是指分爲兩種:一種是UNICODE,一種是ASCII(ps:貌似還是linux上簡單明瞭的- _-utf-8兼容acsII)。

然後如果用vs新建的工程的話。定義了_UNICODE的宏,然後代碼裏的LPCSTR和TCHAR啥的都是wchar_t咯,然後用“E:”這類char*的字符串就會出問題,然後用printf去打印wchar_t的話就會有問題了。。

嗯,最後說解決辦法吧,首先要去掉#include <tchar.h>。然後打開項目的屬性(右鍵)——“C/C++”——“預處理器”——“預處理器定義——編輯”看到 繼承的值 UNICODE和_UNICODE了吧,把下面“從父級或項目默認設置繼承”前面的勾勾去掉,最後保存重新編譯就ok拉~~~

水平有限,必有錯漏,如發現請必指出,互相交流,多多學習~ ^_^


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章