26 #ifndef FILEUTILS_H 27 #define FILEUTILS_H 28 29 30 #include <fstream> 31 #include "SysInfo.h" 32 33 34 namespace FileUtils { 35 36 // Returns 'true' if the given character is a path separator. 37 bool isDirSeparator(const tstring::value_type c); 38 39 // checks if the file or directory exists 40 bool isFileExists(const tstring &filePath); 41 42 // checks is the specified file is a directory 43 // returns false if the path does not exist 44 bool isDirectory(const tstring &filePath); 45 46 //checks if the specified directory is not empty 47 //returns true if the path is an existing directory and it contains at least one file other than "." or "..". 48 bool isDirectoryNotEmpty(const tstring &dirPath); 49 50 // returns directory part of the path. 51 // returns empty string if the path contains only filename. 52 // if the path ends with slash/backslash, returns removeTrailingSlashes(path). 53 tstring dirname(const tstring &path); 54 55 // returns basename part of the path 56 // if the path ends with slash/backslash, returns empty string. 57 tstring basename(const tstring &path); 58 59 /** 60 * Translates forward slashes to back slashes and returns lower case version 61 * of the given string. 62 */ 63 tstring normalizePath(tstring v); 64 65 // Returns suffix of the path. If the given path has a suffix the first 66 // character of the return value is '.'. 67 // Otherwise return value if empty string. 68 tstring suffix(const tstring &path); 69 70 // combines two strings into a path 71 tstring combinePath(const tstring& parent, const tstring& child); 72 73 // removes trailing slashes and backslashes in the path if any 74 tstring removeTrailingSlash(const tstring& path); 75 76 // Creates a file with unique name in the specified base directory, throws an exception if operation fails 77 // path is constructed as <prefix><random number><suffix>. 78 // The function fails and throws exception if 'path' doesn't exist. 79 tstring createTempFile(const tstring &prefix = _T(""), const tstring &suffix = _T(".tmp"), const tstring &path=SysInfo::getTempDir()); 80 81 // Creates a directory with unique name in the specified base directory, throws an exception if operation fails 82 // path is constructed as <prefix><random number><suffix> 83 // The function fails and throws exception if 'path' doesn't exist. 84 tstring createTempDirectory(const tstring &prefix = _T(""), const tstring &suffix = _T(".tmp"), const tstring &basedir=SysInfo::getTempDir()); 85 86 // If the file referenced with "prototype" parameter DOES NOT exist, the return 87 // value is the given path. No new files created. 88 // Otherwise the function creates another file in the same directory as 89 // the given file with the same suffix and with the basename from the 90 // basename of the given file with some random chars appended to ensure 91 // created file is unique. 92 tstring createUniqueFile(const tstring &prototype); 93 94 // Creates directory and subdirectories if don't exist. 95 // Currently supports only "standard" path like "c:\bla-bla" 96 // If 'createdDirs' parameter is not NULL, the given array is appended with 97 // all subdirectories created by this function call. 98 void createDirectory(const tstring &path, tstring_array* createdDirs=0); 99 100 // copies file from fromPath to toPath. Creates output directory if doesn't exist. 101 void copyFile(const tstring& fromPath, const tstring& toPath, bool failIfExists); 102 103 // moves file from fromPath to toPath. Creates output directory if doesn't exist. 104 void moveFile(const tstring& fromPath, const tstring& toPath, bool failIfExists); 105 106 // Throws exception if fails to delete specified 'path'. 107 // Exits normally if 'path' doesn't exist or it has been deleted. 108 // Attempts to strip R/O attribute if delete fails and retry delete. 109 void deleteFile(const tstring &path); 110 // Returns 'false' if fails to delete specified 'path'. 111 // Returns 'true' if 'path' doesn't exist or it has been deleted. 112 // Attempts to strip R/O attribute if delete fails and retry delete. 113 bool deleteFile(const tstring &path, const std::nothrow_t &) throw(); 114 115 // Like deleteFile(), but applies to directories. 116 void deleteDirectory(const tstring &path); 117 bool deleteDirectory(const tstring &path, const std::nothrow_t &) throw(); 118 119 // Deletes all files (not subdirectories) from the specified directory. 120 // Exits normally if all files in 'dirPath' have been deleted or if 121 // 'dirPath' doesn't exist. 122 // Throws exception if 'dirPath' references existing file system object 123 // which is not a directory or when the first failure of file delete 124 // occurs. 125 void deleteFilesInDirectory(const tstring &dirPath); 126 // Deletes all files (not subdirectories) from the specified directory. 127 // Returns 'true' normally if all files in 'dirPath' have been deleted or 128 // if 'dirPath' doesn't exist. 129 // Returns 'false' if 'dirPath' references existing file system object 130 // which is not a directory or if failed to delete one ore more files in 131 // 'dirPath' directory. 132 // Doesn't abort iteration over files if the given directory after the 133 // first failure to delete a file. 134 bool deleteFilesInDirectory(const tstring &dirPath, const std::nothrow_t &) throw(); 135 // Like deleteFilesInDirectory, but deletes subdirectories as well 136 void deleteDirectoryRecursive(const tstring &dirPath); 137 bool deleteDirectoryRecursive(const tstring &dirPath, const std::nothrow_t &) throw(); 138 139 class DirectoryCallback { 140 public: 141 virtual ~DirectoryCallback() {}; 142 143 virtual bool onFile(const tstring& path) { 144 return true; 145 } 146 virtual bool onDirectory(const tstring& path) { 147 return true; 148 } 149 }; 150 151 // Calls the given callback for every file and subdirectory of 152 // the given directory. 153 void iterateDirectory(const tstring &dirPath, DirectoryCallback& callback); 154 155 /** 156 * Replace file suffix, example replaceSuffix("file/path.txt", ".csv") 157 * @param path file path to replace suffix 184 tstring_array findItems() { 185 tstring_array reply; 186 findItems(reply); 187 return reply; 188 } 189 190 DirectoryIterator& findItems(tstring_array& v); 191 192 private: 193 virtual bool onFile(const tstring& path); 194 virtual bool onDirectory(const tstring& path); 195 196 private: 197 bool theRecurse; 198 bool theWithFiles; 199 bool theWithFolders; 200 tstring root; 201 tstring_array items; 202 }; 203 204 // Returns array of all the files/sub-folders from the given directory, empty array if basedir is not a directory. The returned 205 // array is ordered from top down (i.e. dirs are listed first followed by subfolders and files). 206 // Order of subfolders and files is undefined but usually they are sorted by names. 207 inline tstring_array listAllContents(const tstring& basedir) { 208 return DirectoryIterator(basedir).findItems(); 209 } 210 211 // Helper to construct path from multiple components. 212 // 213 // Sample usage: 214 // Construct "c:\Program Files\Java" string from three components 215 // 216 // tstring path = FileUtils::mkpath() << _T("c:") 217 // << _T("Program Files") 218 // << _T("Java"); 219 // 220 class mkpath { 221 public: 222 operator const tstring& () const { 223 return path; 224 } 225 226 mkpath& operator << (const tstring& p) { 227 path = combinePath(path, p); 228 return *this; 229 } 230 231 // mimic std::string 232 const tstring::value_type* c_str() const { 233 return path.c_str(); 234 } 235 private: 236 tstring path; 237 }; 238 239 struct Directory { 240 Directory() { 241 } 242 243 Directory(const tstring &parent, const tstring &subdir) : parent(parent), subdir(subdir) { 244 } 245 246 operator tstring () const { 247 return getPath(); 248 } 249 250 tstring getPath() const { 251 return combinePath(parent, subdir); 252 } 253 254 bool empty() const { 255 return (parent.empty() && subdir.empty()); 256 } 257 258 tstring parent; 259 tstring subdir; 260 }; 261 262 // Deletes list of files and directories in batch mode. 263 // Registered files and directories are deleted when destructor is called. 296 Deleter& appendFile(const tstring& path); 297 298 // Schedule files for deletion. 299 template <class It> 300 Deleter& appendFiles(It b, It e) { 301 for (It it = b; it != e; ++it) { 302 appendFile(*it); 303 } 304 return *this; 305 } 306 307 // Schedule files for deletion in the given directory. 308 template <class It> 309 Deleter& appendFiles(const tstring& dirname, It b, It e) { 310 for (It it = b; it != e; ++it) { 311 appendFile(FileUtils::mkpath() << dirname << *it); 312 } 313 return *this; 314 } 315 316 // Schedule empty directory for deletion with empty roots (up to Directory.parent). 317 Deleter& appendEmptyDirectory(const Directory& dir); 318 319 // Schedule empty directory for deletion without roots. 320 // This is a particular case of appendEmptyDirectory(const Directory& dir) 321 // with Directory(dirname(path), basename(path)). 322 Deleter& appendEmptyDirectory(const tstring& path); 323 324 // Schedule all file from the given directory for deletion. 325 Deleter& appendAllFilesInDirectory(const tstring& path); 326 327 // Schedule directory for recursive deletion. 328 Deleter& appendRecursiveDirectory(const tstring& path); 329 330 void cancel() { 331 paths.clear(); 332 } 333 334 // Deletes scheduled files and directories. After this function 335 // is called internal list of scheduled items is emptied. 336 void execute(); 337 338 private: 339 Paths paths; 340 }; | 26 #ifndef FILEUTILS_H 27 #define FILEUTILS_H 28 29 30 #include <fstream> 31 #include "SysInfo.h" 32 33 34 namespace FileUtils { 35 36 // Returns 'true' if the given character is a path separator. 37 bool isDirSeparator(const tstring::value_type c); 38 39 // checks if the file or directory exists 40 bool isFileExists(const tstring &filePath); 41 42 // checks is the specified file is a directory 43 // returns false if the path does not exist 44 bool isDirectory(const tstring &filePath); 45 46 // checks if the specified directory is not empty 47 // returns true if the path is an existing directory and 48 // it contains at least one file other than "." or "..". 49 bool isDirectoryNotEmpty(const tstring &dirPath); 50 51 // returns directory part of the path. 52 // returns empty string if the path contains only filename. 53 // if the path ends with slash/backslash, 54 // returns removeTrailingSlashes(path). 55 tstring dirname(const tstring &path); 56 57 // returns basename part of the path 58 // if the path ends with slash/backslash, returns empty string. 59 tstring basename(const tstring &path); 60 61 /** 62 * Translates forward slashes to back slashes and returns lower case version 63 * of the given string. 64 */ 65 tstring normalizePath(tstring v); 66 67 // Returns suffix of the path. If the given path has a suffix the first 68 // character of the return value is '.'. 69 // Otherwise return value if empty string. 70 tstring suffix(const tstring &path); 71 72 // combines two strings into a path 73 tstring combinePath(const tstring& parent, const tstring& child); 74 75 // removes trailing slashes and backslashes in the path if any 76 tstring removeTrailingSlash(const tstring& path); 77 78 // Creates a file with unique name in the specified base directory, 79 // throws an exception if operation fails 80 // path is constructed as <prefix><random number><suffix>. 81 // The function fails and throws exception if 'path' doesn't exist. 82 tstring createTempFile(const tstring &prefix = _T(""), 83 const tstring &suffix = _T(".tmp"), 84 const tstring &path=SysInfo::getTempDir()); 85 86 // Creates a directory with unique name in the specified base directory, 87 // throws an exception if operation fails 88 // path is constructed as <prefix><random number><suffix> 89 // The function fails and throws exception if 'path' doesn't exist. 90 tstring createTempDirectory(const tstring &prefix = _T(""), 91 const tstring &suffix = _T(".tmp"), 92 const tstring &basedir=SysInfo::getTempDir()); 93 94 // If the file referenced with "prototype" parameter DOES NOT exist, 95 // the return value is the given path. No new files created. 96 // Otherwise the function creates another file in the same directory as 97 // the given file with the same suffix and with the basename from the 98 // basename of the given file with some random chars appended to ensure 99 // created file is unique. 100 tstring createUniqueFile(const tstring &prototype); 101 102 // Creates directory and subdirectories if don't exist. 103 // Currently supports only "standard" path like "c:\bla-bla" 104 // If 'createdDirs' parameter is not NULL, the given array is appended with 105 // all subdirectories created by this function call. 106 void createDirectory(const tstring &path, tstring_array* createdDirs=0); 107 108 // copies file from fromPath to toPath. 109 // Creates output directory if doesn't exist. 110 void copyFile(const tstring& fromPath, const tstring& toPath, 111 bool failIfExists); 112 113 // moves file from fromPath to toPath. 114 // Creates output directory if doesn't exist. 115 void moveFile(const tstring& fromPath, const tstring& toPath, 116 bool failIfExists); 117 118 // Throws exception if fails to delete specified 'path'. 119 // Exits normally if 'path' doesn't exist or it has been deleted. 120 // Attempts to strip R/O attribute if delete fails and retry delete. 121 void deleteFile(const tstring &path); 122 // Returns 'false' if fails to delete specified 'path'. 123 // Returns 'true' if 'path' doesn't exist or it has been deleted. 124 // Attempts to strip R/O attribute if delete fails and retry delete. 125 bool deleteFile(const tstring &path, const std::nothrow_t &) throw(); 126 127 // Like deleteFile(), but applies to directories. 128 void deleteDirectory(const tstring &path); 129 bool deleteDirectory(const tstring &path, const std::nothrow_t &) throw(); 130 131 // Deletes all files (not subdirectories) from the specified directory. 132 // Exits normally if all files in 'dirPath' have been deleted or if 133 // 'dirPath' doesn't exist. 134 // Throws exception if 'dirPath' references existing file system object 135 // which is not a directory or when the first failure of file delete 136 // occurs. 137 void deleteFilesInDirectory(const tstring &dirPath); 138 // Deletes all files (not subdirectories) from the specified directory. 139 // Returns 'true' normally if all files in 'dirPath' have been deleted or 140 // if 'dirPath' doesn't exist. 141 // Returns 'false' if 'dirPath' references existing file system object 142 // which is not a directory or if failed to delete one ore more files in 143 // 'dirPath' directory. 144 // Doesn't abort iteration over files if the given directory after the 145 // first failure to delete a file. 146 bool deleteFilesInDirectory(const tstring &dirPath, 147 const std::nothrow_t &) throw(); 148 // Like deleteFilesInDirectory, but deletes subdirectories as well 149 void deleteDirectoryRecursive(const tstring &dirPath); 150 bool deleteDirectoryRecursive(const tstring &dirPath, 151 const std::nothrow_t &) throw(); 152 153 class DirectoryCallback { 154 public: 155 virtual ~DirectoryCallback() {}; 156 157 virtual bool onFile(const tstring& path) { 158 return true; 159 } 160 virtual bool onDirectory(const tstring& path) { 161 return true; 162 } 163 }; 164 165 // Calls the given callback for every file and subdirectory of 166 // the given directory. 167 void iterateDirectory(const tstring &dirPath, DirectoryCallback& callback); 168 169 /** 170 * Replace file suffix, example replaceSuffix("file/path.txt", ".csv") 171 * @param path file path to replace suffix 198 tstring_array findItems() { 199 tstring_array reply; 200 findItems(reply); 201 return reply; 202 } 203 204 DirectoryIterator& findItems(tstring_array& v); 205 206 private: 207 virtual bool onFile(const tstring& path); 208 virtual bool onDirectory(const tstring& path); 209 210 private: 211 bool theRecurse; 212 bool theWithFiles; 213 bool theWithFolders; 214 tstring root; 215 tstring_array items; 216 }; 217 218 // Returns array of all the files/sub-folders from the given directory, 219 // empty array if basedir is not a directory. The returned 220 // array is ordered from top down (i.e. dirs are listed first followed 221 // by subfolders and files). 222 // Order of subfolders and files is undefined 223 // but usually they are sorted by names. 224 inline tstring_array listAllContents(const tstring& basedir) { 225 return DirectoryIterator(basedir).findItems(); 226 } 227 228 // Helper to construct path from multiple components. 229 // 230 // Sample usage: 231 // Construct "c:\Program Files\Java" string from three components 232 // 233 // tstring path = FileUtils::mkpath() << _T("c:") 234 // << _T("Program Files") 235 // << _T("Java"); 236 // 237 class mkpath { 238 public: 239 operator const tstring& () const { 240 return path; 241 } 242 243 mkpath& operator << (const tstring& p) { 244 path = combinePath(path, p); 245 return *this; 246 } 247 248 // mimic std::string 249 const tstring::value_type* c_str() const { 250 return path.c_str(); 251 } 252 private: 253 tstring path; 254 }; 255 256 struct Directory { 257 Directory() { 258 } 259 260 Directory(const tstring &parent, 261 const tstring &subdir) : parent(parent), subdir(subdir) { 262 } 263 264 operator tstring () const { 265 return getPath(); 266 } 267 268 tstring getPath() const { 269 return combinePath(parent, subdir); 270 } 271 272 bool empty() const { 273 return (parent.empty() && subdir.empty()); 274 } 275 276 tstring parent; 277 tstring subdir; 278 }; 279 280 // Deletes list of files and directories in batch mode. 281 // Registered files and directories are deleted when destructor is called. 314 Deleter& appendFile(const tstring& path); 315 316 // Schedule files for deletion. 317 template <class It> 318 Deleter& appendFiles(It b, It e) { 319 for (It it = b; it != e; ++it) { 320 appendFile(*it); 321 } 322 return *this; 323 } 324 325 // Schedule files for deletion in the given directory. 326 template <class It> 327 Deleter& appendFiles(const tstring& dirname, It b, It e) { 328 for (It it = b; it != e; ++it) { 329 appendFile(FileUtils::mkpath() << dirname << *it); 330 } 331 return *this; 332 } 333 334 // Schedule empty directory for deletion with empty roots 335 // (up to Directory.parent). 336 Deleter& appendEmptyDirectory(const Directory& dir); 337 338 // Schedule empty directory for deletion without roots. 339 // This is a particular case of 340 // appendEmptyDirectory(const Directory& dir) 341 // with Directory(dirname(path), basename(path)). 342 Deleter& appendEmptyDirectory(const tstring& path); 343 344 // Schedule all file from the given directory for deletion. 345 Deleter& appendAllFilesInDirectory(const tstring& path); 346 347 // Schedule directory for recursive deletion. 348 Deleter& appendRecursiveDirectory(const tstring& path); 349 350 void cancel() { 351 paths.clear(); 352 } 353 354 // Deletes scheduled files and directories. After this function 355 // is called internal list of scheduled items is emptied. 356 void execute(); 357 358 private: 359 Paths paths; 360 }; |