using System; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text.RegularExpressions; using Core.Common.Utils.Properties; using log4net; namespace Core.Common.Utils.IO { /// /// File manipulations /// public static class FileUtils { private static readonly ILog Log = LogManager.GetLogger(typeof(FileUtils)); /// /// Copies the source file to the target destination; if the file /// already exists, it will be overwritten by default. /// /// Source file path. /// Destination file path. /// True if the destination file should be overwritten when it exists, false otherwise. public static void CopyFile(string sourcePath, string targetPath, bool overwrite = true) { var sourceFullPath = Path.GetFullPath(sourcePath); var targetFullPath = Path.GetFullPath(targetPath); if (sourceFullPath == targetFullPath) { return; } if (File.Exists(targetPath)) { if (!overwrite) { return; } File.Delete(targetPath); } File.Copy(sourcePath, targetPath); } /// /// Copy files in a directory (and its subdirectories) to another directory. /// /// Source directory. /// Destination directory. /// Exclude folder from being copied. public static void CopyAll(DirectoryInfo source, DirectoryInfo target, string ignorePath = "") { foreach (var diSourceSubDir in source.GetDirectories().Where(diSourceSubDir => diSourceSubDir.Name != ignorePath)) { if (Directory.Exists(target.FullName) == false) { Directory.CreateDirectory(target.FullName); } var nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name); CopyAll(diSourceSubDir, nextTargetSubDir, ignorePath); } foreach (var fi in source.GetFiles()) { Log.DebugFormat(Resource.FileUtils_CopyAll_Copying_0_1_, target.FullName, fi.Name); if (!target.Exists) { target.Create(); } var path = Path.Combine(target.ToString(), fi.Name); fi.CopyTo(path, true); } } /// /// Make all files and sub-directories writable. /// /// public static void MakeWritable(string path) { if (Directory.Exists(path)) { File.SetAttributes(path, FileAttributes.Normal); } var di = new DirectoryInfo(path); foreach (DirectoryInfo di2 in di.GetDirectories()) { File.SetAttributes(path, FileAttributes.Normal); MakeWritable(Path.Combine(path, di2.Name)); } // Copy each file into it's new directory. foreach (FileInfo fi in di.GetFiles()) { String filePath = Path.Combine(path, fi.Name); File.SetAttributes(filePath, FileAttributes.Normal); } } /// /// Check if the search item path is a subdirectory of the . /// /// Directory path. /// Name of the supposed child directory. /// True if is a direct child of , false otherwise. public static bool IsSubdirectory(string rootDir, string searchItem) { if (rootDir.StartsWith(@"\\")) //network disk? { return searchItem.StartsWith(rootDir, StringComparison.InvariantCultureIgnoreCase); } var rootDirAbsolute = AppendDirectorySeparatorIfMissing(Path.GetFullPath(rootDir)); var searchDirAbsolute = AppendDirectorySeparatorIfMissing(Path.GetFullPath(searchItem)); return searchDirAbsolute.Length > rootDirAbsolute.Length && searchDirAbsolute.StartsWith(rootDirAbsolute, StringComparison.InvariantCultureIgnoreCase); } /// /// Ensures a closing directory separator in . /// /// Directory to ensure closing directory separator. /// with closing directory separator. public static string AppendDirectorySeparatorIfMissing(string directory) { if (!directory.EndsWith(Path.DirectorySeparatorChar.ToString())) { directory += Path.DirectorySeparatorChar; } return directory; } /// /// Compares two directory strings. /// /// Directory path. /// Directory path to compare. /// True if the string paths are equal. public static bool CompareDirectories(string rootDir, string searchItem) { var root = Path.GetFullPath(rootDir); var search = Path.GetFullPath(searchItem); return root == search; } /// /// Returns a relative path string from a full path. /// /// Directory path. /// Directory path to make relative to . /// Relative path from . public static string GetRelativePath(string rootDir, string filePath) { if (rootDir == null || filePath == null) { return filePath; } if (rootDir.StartsWith("\\\\") && IsSubdirectory(rootDir, filePath)) //network disk? { return "." + filePath.Substring(rootDir.Length); } try { // Folders must end in a slash rootDir = AppendDirectorySeparatorIfMissing(rootDir); var folderUri = new Uri(rootDir); var pathUri = new Uri(filePath); return Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri).ToString().Replace('/', Path.DirectorySeparatorChar)); } catch (Exception) { // gulp: return original filepath } return filePath; } /// /// Create dir if not exists. /// /// File path to a directory. /// Optional flag to delete the specified directory if it does exist when set to true. /// When: /// The directory specified by is read-only /// Furthermore when is true: /// A file with the same name and location specified by exists. -or- /// The directory is the application's current working directory. /// /// When: The caller does not have the required permission. /// /// is a zero-length string, contains only white space, or contains one or more invalid characters as defined by . -or- /// is prefixed with, or contains only a colon character (:). /// is null. /// /// The specified path, file name, or both exceed the system-defined maximum length. /// For example, on Windows-based platforms, paths must be less than 248 characters and file names must be less than 260 characters. /// The specified path is invalid (for example, it is on an unmapped drive). /// contains a colon character (:) that is not part of a drive label ("C:\"). public static void CreateDirectoryIfNotExists(string path, bool deleteIfExists = false) { if (Directory.Exists(path)) { //replace the directory with a one if (deleteIfExists) { Directory.Delete(path, true); Directory.CreateDirectory(path); } } else { Directory.CreateDirectory(path); } } /// /// Initializes filesystemwatcher. /// /// public static FileSystemWatcher CreateWatcher() { // use built-in filesystemwatcher class to monitor creation/modification/deletion of files // example http://www.codeguru.com/csharp/csharp/cs_network/article.php/c6043/ var watcher = new FileSystemWatcher { IncludeSubdirectories = false, NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Size }; return watcher; } /// /// Checks wether the path is a valid relative path. /// /// /// public static bool PathIsRelative(string path) { return !Path.IsPathRooted(path); } /// /// Replaces text in a file. /// /// Path of the text file. /// Text to search for. /// Text to replace the search text. public static void ReplaceInFile(string filePath, string searchText, string replaceText) { var reader = new StreamReader(filePath); string content = reader.ReadToEnd(); reader.Close(); content = Regex.Replace(content, searchText, replaceText); var writer = new StreamWriter(filePath); writer.Write(content); writer.Close(); } /// /// Creates a temporary directory. /// /// Path to temporary directory. public static string CreateTempDirectory() { string path = Path.GetFileNameWithoutExtension(Path.GetRandomFileName()); Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), path)); return Path.Combine(Path.GetTempPath(), path); } /// /// Check if the content of two files are equal. /// /// First file path. /// Second file path. /// public static bool FilesAreEqual(string file1Path, string file2Path) { var first = new FileInfo(file1Path); var second = new FileInfo(file2Path); if (first.Length != second.Length) { return false; } const int bytesToRead = sizeof(Int64); var iterations = (int) Math.Ceiling((double) first.Length/bytesToRead); using (FileStream fs1 = first.OpenRead()) { using (FileStream fs2 = second.OpenRead()) { var one = new byte[bytesToRead]; var two = new byte[bytesToRead]; for (int i = 0; i < iterations; i++) { fs1.Read(one, 0, bytesToRead); fs2.Read(two, 0, bytesToRead); if (BitConverter.ToInt64(one, 0) != BitConverter.ToInt64(two, 0)) { return false; } } } } return true; } /// /// Checks if the extension of a file belongs to the . /// /// "My file format1 (*.ext1)|*.ext1|My file format2 (*.ext2)|*.ext2". /// Path to a file or filename including extension. /// public static bool FileMatchesFileFilterByExtension(string fileFilter, string path) { if (String.IsNullOrEmpty(Path.GetExtension(path))) { return false; } return Regex.Match(fileFilter, String.Format(@"(\||\;)+\s*\*\{0}", Path.GetExtension(path))).Success; } /// /// Deletes the given file or directory if it exists. /// /// Path of the file or directory to delete. public static void DeleteIfExists(string path) { if (!File.Exists(path) & !Directory.Exists(path)) { return; } var attributes = File.GetAttributes(path); // if file is readonly - make it non-readonly if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) { File.SetAttributes(path, attributes ^ FileAttributes.ReadOnly); } // now delete everything if (File.Exists(path)) { File.Delete(path); } else if (Directory.Exists(path)) { foreach (var path2 in Directory.GetDirectories(path).Union(Directory.GetFiles(path))) { DeleteIfExists(path2); } Directory.Delete(path); } } /// /// Checks if could be a valid file. /// /// File name to check. /// True if fileName could be used as a valid file name, false otherwise. public static bool IsValidFileName(string fileName) { return fileName != null && fileName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 && fileName.Trim().Length > 0; } /// /// Checks if directory is empty. /// /// The path to the directory. /// true is directory exists and is empty, false otherwise. public static bool IsDirectoryEmpty(string path) { if (!Directory.Exists(path)) { return false; } return !Directory.EnumerateFileSystemEntries(path).Any(); } /// /// Computes the checksum for a given file. /// /// The file path. /// The checksum. /// Uses the MD5 checksum algorithm. public static string GetChecksum(string filePath) { using (var md5Algorithm = MD5.Create()) { using (var stream = File.OpenRead(filePath)) { var computedByteHash = md5Algorithm.ComputeHash(stream); return BitConverter.ToString(computedByteHash).Replace("-", "").ToLower(); } } } /// /// Verifies that a given file matches with a checksum. /// /// The file path. /// The checksum to be matched. /// True if the checksum matches; false otherwise. /// public static bool VerifyChecksum(string filePath, string checksumToBeMatched) { var checksum = GetChecksum(filePath); return Equals(checksumToBeMatched, checksum); } /// /// Check if two paths are equal. /// This prevents failure of forward and backward slashes. /// It checks on full path names via . /// public static bool PathsAreEqual(string path1, string path2) { var info1 = new FileInfo(path1); var info2 = new FileInfo(path2); return info1.FullName == info2.FullName; } } }