现在的位置: 首页 > 综合 > 正文

c++与erlang实现目录遍历

2013年05月15日 ⁄ 综合 ⁄ 共 2521字 ⁄ 字号 评论关闭
http://www.toquick.com/index.php/archives/66

 c++与erlang实现目录遍历

最近在写一个windows客户端,其中需要对一个目录进行遍历,并进行某些操作。
使用C++,我采用模板函数,通过自定义的Action完成对遍历中各种文件目录的特定操作。
其代码如下:

// lpEntry 扫描的目录
	// level 扫描的深度,LEVEL_INFINATE表示扫描所有的文件
	// action 模板参数实例(functor),执行特定动作
	#define LEVEL_INFINATE 0xFFFFFFFF
	template< class PredAction >
	int dir_scan( LPCTSTR lpEntry, UINT level, PredAction& action)
	{
		static UINT glevel = 0;
		if( level != LEVEL_INFINATE )
		{
			if( glevel++ > level ) return 1;
		}

		if( !lpEntry || _tcslen(lpEntry) <= 0 ) return -1;

		if( _taccess( lpEntry, 0 ) != 0 )	//目录或文件存在
		{
			return -1;
		}

		struct _stat sb;
		if( _tstat( lpEntry, &sb ) != 0  ) // 获取信息失败
		{
			return -2;
		}
		if( !(sb.st_mode | _S_IFDIR) )	//不是目录
		{
			return -3;
		}

		// 开始遍历
		tstring sDir = lpEntry;
		if( sDir.at( sDir.length()-1) != _T('//') )
			sDir.push_back(_T('//'));

		tstring sFind = sDir +  _T("*.*");

		struct _tfinddata_t fd;
		intptr_t handle = _tfindfirst( const_cast<LPTSTR>(sFind.c_str()), &fd );
		if( handle == -1 ) return -1;

		int nFind = 0;
		while( nFind == 0 )
		{
			if ( _tcscmp(fd.name,_T(".")) != 0  && _tcscmp(fd.name, _T("..")) != 0 )
			{
				if( fd.attrib & _A_SUBDIR ) // 子目录
				{
					tstring strSubDir = sDir+fd.name;
					action( strSubDir.c_str(), false );
					dir_scan( strSubDir.c_str(),
                                           level==LEVEL_INFINATE?level:level+1, action );
				}
				else		// 文件
				{
					action( tstring( sDir+fd.name).c_str(), true );
				}
			}
			nFind = _tfindnext( handle, &fd );
		}
		_findclose( handle );
		return 0;
	};

这个时候我用erlang实现了同样功能的目录扫描函数:

-module(dir_scan).
-export([dir_scan/3, test/0, print/2]).
-define(INFINATE_LEVEL, -1).

-include_lib(”kernel/include/file.hrl”).

dir_scan(Path, Level, Action) when is_list(Path), is_function(Action, 2) ->
	case file:list_dir(Path) of
		{ok, Files} ->
			dir_scan(Path, Files, 0, Level, Action);
		{error, Reason} ->
			{error, {Path, Reason}}
		end.    

dir_scan(Top, [F | Tail], CurLevel, Level, Action) ->
    if
    	Level == ?INFINATE_LEVEL; CurLevel =< Level ->
    		F2 = Top ++ “/” ++ F,
    		case file:read_file_info(F2) of
    			{ok, FileInfo} when FileInfo#file_info.type == directory -> %% directory
    				Action(F2, true), % do action
    				NewLevel = case Level of
    					?INFINATE_LEVEL ->
    						Level;
    					Other ->
    						Level - 1
    					end,
    				case dir_scan(F2, NewLevel, Action) of
    					ok ->
    						dir_scan(Top, Tail, CurLevel, Level, Action);
    					{error, Reason} ->
    						{error, Reason}
    				end;
    		  {ok, FileInfo} when FileInfo#file_info.type == regular -> %% normal file
    		  	Action(F2, false), % do action
    		  	dir_scan(Top, Tail, CurLevel, Level, Action);
    		  _Other ->
    		  	dir_scan(Top, Tail, CurLevel, Level, Action)
    		end;
    	true ->
    		ok
    end;

dir_scan(_Top, [], _CurLevel, _Level, _Action) ->
	ok.

查看两者代码量,相差无几均为60行左右,只是erlang的代码因为没有循环,因此嵌套比较深,不是太美观。
然后看看速度:
erlang版本,我对某个目录进行遍历,对应文件数据不做任何处理,运行10次平均用时77999(microsecond)微妙
C++版本,模板参数Action中operator()为空,平均运行时间为16000微妙。
从中可以看出c++性能为erlang的5倍左右。
erlang采用c实现,而c++与c间的效率差距20%左右,因此c++比erlang运行速度快5倍也不足为其。
这里再次证明了erlang的应用范围及特性,erlang适合分布式程序的开发,开发迅速,容错性好,平台无关,具有成熟的模型。如果没有并发那么erlang存在的意义会大打折扣。

抱歉!评论已关闭.