visitor.cpp
资源名称:treesize.zip [点击查看]
上传用户:dfhlxjd
上传日期:2007-01-07
资源大小:12k
文件大小:4k
源码类别:
Shell编程
开发平台:
Visual C++
- //----------------------------------------
- // (c) Reliable Software 1997
- //----------------------------------------
- #include "visitor.h"
- #include "main.h"
- class FileIter
- {
- public:
- FileIter(char const * pattern);
- ~FileIter()
- {
- FindClose(_handle);
- }
- bool AtEnd() const {return _atEnd;}
- void Advance()
- {
- _atEnd = !FindNextFile (_handle, &_data);
- }
- char const * GetFileName() const {return _data.cFileName;}
- protected:
- bool _atEnd;
- HANDLE _handle;
- WIN32_FIND_DATA _data;
- };
- FileIter::FileIter (char const * pattern)
- :_atEnd (false)
- {
- _handle = FindFirstFile (pattern, &_data);
- if (_handle == INVALID_HANDLE_VALUE)
- {
- int err = GetLastError ();
- if (err == ERROR_FILE_NOT_FOUND)
- _atEnd = true;
- else
- {
- throw WinException ("Internal error: FindFirstFile failed");
- }
- }
- // skip links to the current and parent directories
- while (!_atEnd && _data.cFileName [0] == '.')
- _atEnd = !FindNextFile (_handle, &_data);
- }
- // Usage:
- // Declare a Sizer visitor
- // Declare a Traversal using full path
- // Retrieve total size from the visitor
- Traversal::Traversal (Path & path, Visitor & visitor)
- : _visitor (visitor)
- {
- TraverseTree (path);
- }
- Traversal::Traversal (char const * directoryName, Visitor & visitor)
- : _visitor (visitor)
- {
- Path path(directoryName);
- TraverseTree (path);
- }
- void Traversal::TraverseTree (Path & curPath)
- {
- // list all *.* files and directories
- for (FileIter iter (curPath.WildcardPath ()); !iter.AtEnd (); iter.Advance ())
- {
- char const * name = iter.GetFileName ();
- if (_visitor.Visit (name))
- {
- // Visitor found folder
- curPath.DirDown (name);
- TraverseTree (curPath);
- curPath.DirUp ();
- }
- }
- }
- class File
- {
- public:
- ~File () { Close (); }
- bool FileOk () { return _hFile != INVALID_HANDLE_VALUE; }
- ULONG GetSize () const { return _size; }
- void InitSize ();
- static bool IsFolder (char const * path);
- protected:
- File () : _hFile (INVALID_HANDLE_VALUE), _size (0) {}
- void OpenReadOnly (char const * path);
- void Close ();
- HANDLE _hFile;
- ULONG _size;
- };
- bool File::IsFolder (char const * path)
- {
- SetLastError(NO_ERROR);
- bool rval = false;
- try
- {
- DWORD attr = GetFileAttributes (path);
- rval = (attr != 0xffffffff) && (attr & FILE_ATTRIBUTE_DIRECTORY);
- }
- catch (...)
- {
- rval = false;
- }
- return rval;
- }
- void File::OpenReadOnly (char const *path)
- {
- _hFile = CreateFile (
- path,
- GENERIC_READ,
- FILE_SHARE_READ,
- 0,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- 0);
- if (!FileOk ())
- {
- throw "Internal error: Read only open file failed.";
- }
- }
- void File::Close ()
- {
- if (FileOk())
- {
- CloseHandle (_hFile);
- _hFile = INVALID_HANDLE_VALUE;
- }
- }
- void File::InitSize ()
- {
- ULONG sizeHigh;
- _size = ::GetFileSize (_hFile, &sizeHigh);
- if (sizeHigh != 0)
- throw "Internal error: File too big (> 4GB)";
- if (0xFFFFFFFF== _size && NO_ERROR != GetLastError ())
- {
- Close ();
- throw "Internal error: Get file size failed.";
- }
- }
- class FileInfo: public File
- {
- public:
- FileInfo (char const *path)
- {
- OpenReadOnly (path);
- InitSize ();
- }
- };
- bool Sizer::Visit (char const * name)
- {
- bool recurse = false;
- // IsFolder sets the thread error
- SetLastError(NO_ERROR);
- if (File::IsFolder (name))
- {
- recurse = true;
- }
- else
- {
- if (GetLastError() == NO_ERROR)
- {
- try
- {
- FileInfo info (name);
- _totalSize += info.GetSize ();
- }
- catch (...)
- {
- // file info couldn't be fetched - not a fatal error,
- // just skip counting...
- }
- }
- }
- return recurse;
- }