• 从C++遍历路径中含有汉字的文件夹看宽窄字符串转换的问题


    整理者:finallyliuyu

        NLP研究者或者开发人员如果选用C++语言作为开发工具。那么首先需要克服两个难题。

        第一个难题是:学会在C++中使用正则表达式。鉴于C++本身并不支持正则表达式,所以我们需要借助第三方库boost.中的regex子库。网络上有很多关于boost的安装方法,比如有的方法介绍如何部分安装boost库,我这里也整理了一个如何完全安装boost库的方法:《C++安装boost》这个我试验过,上面的方法是可行的。但是安装boost库之前,需要安装python26

        第二个难题是:宽窄字符串转换问题,这个问题目前我只是整理了部分解决方案。日后有新的总结会增加进来。此篇博文给出针对第二个难题的一些知识整理。以下博文将分为两个部分:第一个部分讲解:利用boost正则库进行字符串处理的时候需要进行的字符串转换;第二个部分讲解:遍历路径中含有汉字的文件夹时的路径字符串转换问题。

    第一部分:利用boost正则库进行字符串处理的时候需要进行的字符串转换

    如果字符串中含有汉字,应该使用的正则表达式类型为boost::wregex;

    还要将字符串从string转换为wstring

    string->wstring:的大概思路是将string用c_str()转换成c格式的字符串,然后将char 型的字符串转化成 wchar_t型的字符串,然后wchart_t的字符串转化成wstring

    string->wstring代码如下:

    ************************************************************************/
    /*  功能:将窄字符转化成宽字符,string->wstring                         */
    /************************************************************************/
    wstring myMultibyteToWideChar(string sResult)
    {
    	int iWLen=MultiByteToWideChar( CP_ACP, 0, sResult.c_str(), sResult.size(), 0, 0 );// 计算转换后宽字符串的长度。(不包含字符串结束符)
    	wchar_t *lpwsz= new wchar_t [iWLen+1];
    	MultiByteToWideChar( CP_ACP, 0, sResult.c_str(), sResult.size(), lpwsz, iWLen ); // 正式转换。
    	lpwsz[iWLen] = L'\0'; 
    	wstring wsResult(lpwsz);
    	delete []lpwsz;
    	return wsResult;
    }

    函数中调用了windows.h中的函数MultiByteToWideChar函数将char型字符串转化成wchar_t型的字符串。

    为了让经过正则处理后的字符串在控制台正常显示,还有将wstring->string

    代码如下(代码中也用到了windows.h中的函数):

    /************************************************************************/
    /* 将宽字符串转化成窄字符串用于输出                                     */
    /************************************************************************/
    string myWideCharToMultibyte(wstring wsResult)
    {	string sResult;
    	int iLen= WideCharToMultiByte( CP_ACP, NULL, wsResult.c_str(), -1, NULL, 0, NULL, FALSE ); // 计算转换后字符串的长度。(包含字符串结束符)
    	char *lpsz= new char[iLen];
    	WideCharToMultiByte( CP_OEMCP, NULL, wsResult.c_str(), -1, lpsz, iLen, NULL, FALSE); // 正式转换。
    	sResult.assign( lpsz, iLen-1 ); // 对string对象进行赋值。
    	delete []lpsz;
    	return sResult;
    
    
    
    
    }

    第二部分:

    遍历路径中含有汉字的文件夹时的路径字符串转换问题。

    首先给出测试代码:

    int _tmain(int argc, _TCHAR* argv[])
    {
     	int end;
    		
    	FindFile("E:\\旧电脑");
       cout<<"finish"<<endl;
    	
    	cin>>end;
    
    
    }
     
     
     
     
     
     
     
     
     
     
     
    文件夹情况如下:
    QQ截图未命名 
     
    其中破旧电脑的子文件夹下面还有文件:
    QQ截图未命名 

    此部分给出两种方法。

    方法一(修改来自同学刘洋的代码)

    用此方法要先将VS2008项目属性设置为Multibyte。显示的字符串将会出现乱码

    void FindFile(char * filePath)
    {  
    	WIN32_FIND_DATA  FileData;   //这两个是系统参数,hFile是句柄 ,FileData是一些标志
    	HANDLE   hFile; 
    	char dir[1000];
    	memset(dir,0,1000);
    	sprintf_s(dir,1000,"%s%s",filePath,"\\*.*");
    	hFile=FindFirstFile(dir,&FileData);
    	
    	if (hFile == INVALID_HANDLE_VALUE) //FindFirstFile()如果没找到进行这一步
    	{
    		printf ("%s\n", "没有找到文件");
    		return ;
    	} 
    	bool bFinish=false;
    	while(!bFinish)
    	{	
    		   char *temp= FileData.cFileName;//这个就是FindFirstFile()返回的文件的名字
    			if((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)&&strcmp(temp,".")&&strcmp(temp,"..") )//判断返回的东西是不是目录或者"." "..",因为一个目录下都有"." ,".."两个文件夹
    			{
    				char  dirassist[3000];
    				memset(dirassist,0,3000);
    				sprintf_s(dirassist,3000,"%s%s%s",filePath,"\\",temp);
    				FindFile(dirassist);
    			
    
    
    			}
    			//	else
    			if(((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0))//判断是不是ClassList.txt这个文件
    			{
    				cout<<FileData.cFileName<<endl;
    			
    			}
    
    			bFinish = (FindNextFile(hFile, &FileData) == false);//看目录下还有没有文件,有的话bFinish=flase 继续循环
    	}
     
    结果如下:

    LDSBSYZW`(~0IK(9U2KYIDR

     
    方法二(来自网友茅柳野)
    此版本无需改变工程字符集,默认为unicode即可
    /************************************************************************/
    /* 遍历文件夹                                                                     */
    /************************************************************************/
     void FindFile(wchar_t *pFilePath) {
    	 WIN32_FIND_DATA FindFileData;
    	 HANDLE hFind = INVALID_HANDLE_VALUE;
    	 wchar_t  DirSpec[MAX_PATH + 1];// 指定路径 
    	 DWORD dwError;
    	 wcsncpy (DirSpec, pFilePath, wcslen(pFilePath) + 1);
    	 wcsncat (DirSpec, L"\\\*", 3);
    	 hFind = FindFirstFile(DirSpec, &FindFileData);
    	 if (hFind == INVALID_HANDLE_VALUE) {
    		 wprintf(L"Invalid file handle. Error is %u ", GetLastError());
    		 return ;
    	 } 
    	 else if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY )
    		 {
    			 wchar_t temp[3000];
    			 memset(temp,0,3000*sizeof(wchar_t));
    		    wprintf_s(temp,L"%s\\%s\n",pFilePath,FindFileData.cFileName);
    			int iLen= WideCharToMultiByte( CP_ACP, NULL, temp, -1, NULL, 0, NULL, FALSE ); // 计算转换后字符串的长度。(包含字符串结束符)
    			char *lpsz= new char[iLen];
    			WideCharToMultiByte( CP_OEMCP, NULL, temp, -1, lpsz, iLen, NULL, FALSE); // 正式转换。
    			cout<<lpsz<<endl;
    			delete []lpsz;
    	     } 
    	 else if(FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY
    		 && wcscmp(FindFileData.cFileName, L".") != 0
    		 && wcscmp(FindFileData.cFileName, L"..") != 0) 
    			{   //找到目录
    			 wchar_t Dir[MAX_PATH + 1];
    			 wcscpy(Dir, pFilePath);
    			 wcsncat(Dir, L"\\", 2);
    			 wcscat(Dir, FindFileData.cFileName);
    
    			 FindFile(Dir);
    			 }
    
    		while (FindNextFile(hFind, &FindFileData) != 0) 
    		{
    		 if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) 
    		 {   //找到文件
    			 //fwprintf(fp, L"%s\\", pFilePath);
    			 //fwprintf(fp, L"%s\n", FindFileData.cFileName);
    			 wchar_t temp[3000];
    			 memset(temp,0,3000*sizeof(wchar_t));
    			 wcscpy(temp,pFilePath);
    			 wcscat(temp,FindFileData.cFileName);
    			
    			 int iLen= WideCharToMultiByte( CP_ACP, NULL, temp, -1, NULL, 0, NULL, FALSE ); // 计算转换后字符串的长度。(包含字符串结束符)
    			 char *lpsz= new char[iLen];
    			 WideCharToMultiByte( CP_OEMCP, NULL, temp, -1, lpsz, iLen, NULL, FALSE); // 正式转换。
    			 cout<<lpsz<<endl;
    			 delete []lpsz;
    			 
    		 } 
    		 else if(FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY
    			 && wcscmp(FindFileData.cFileName, L".") != 0
    			 && wcscmp(FindFileData.cFileName, L"..") != 0) 
    		 { //找到目录
    				 wchar_t Dir[MAX_PATH + 1];
    				 wcscpy(Dir, pFilePath);
    				 wcsncat(Dir, L"\\", 2);
    				 wcscat(Dir, FindFileData.cFileName);
    				 FindFile(Dir);
    		 }
    	 }
    
    	 dwError = GetLastError();
    	 FindClose(hFind);
    	 if (dwError != ERROR_NO_MORE_FILES)
    	 {
    		 wprintf (L"FindNextFile error. Error is %u ", dwError);
    		 return;
    	 }
     }
    
     
    运行结果如下:

    %2S7~}Y1ZPP`_Y3AOLF0IE1

  • 相关阅读:
    SIP穿越NAT SIP穿越防火墙-SBC
    安卓SAX解析XML文件
    C#进阶系列——WebApi 异常处理解决方案
    C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解
    C#进阶系列——WebApi 接口参数不再困惑:传参详解
    C#进阶系列——WebApi 身份认证解决方案:Basic基础认证
    C#进阶系列——WebApi 跨域问题解决方案:CORS
    C#进阶系列——WebApi 接口测试工具:WebApiTestClient
    微信公众平台向特定用户推送消息
    JSONP跨域的原理解析
  • 原文地址:https://www.cnblogs.com/finallyliuyu/p/1830219.html
Copyright © 2020-2023  润新知