diff --git a/DTLib/Extensions/StringConverter.cs b/DTLib/Extensions/StringConverter.cs index a3ce624..80d94b1 100644 --- a/DTLib/Extensions/StringConverter.cs +++ b/DTLib/Extensions/StringConverter.cs @@ -44,30 +44,47 @@ public static class StringConverter public static bool StartsWith(this string s, char c) => s[0] == c; public static bool EndsWith(this string s, char c) => s[s.Length - 1] == c; - public static string MergeToString(params object[] parts) + public static string MergeToString(params TVal[] parts) { + if (parts.Length == 0) + return ""; StringBuilder builder = new(); for (int i = 0; i < parts.Length; i++) builder.Append(parts[i]); return builder.ToString(); } - public static string MergeToString(this IEnumerable collection, string separator) + public static string MergeToString(TSep separator, params TVal[] parts) { - StringBuilder builder = new(); - foreach (T elem in collection) - { - builder.Append(elem); - builder.Append(separator); - } - if (builder.Length == 0) + if (parts.Length == 0) return ""; - builder.Remove(builder.Length - separator.Length, separator.Length); + StringBuilder builder = new(); + builder.Append(parts[0]); + for (int i = 1; i < parts.Length; i++) + { + builder.Append(separator); + builder.Append(parts[i]); + } return builder.ToString(); } - public static string MergeToString(this IEnumerable collection) + + public static string MergeToString(this IEnumerable collection, TSep separator) { StringBuilder builder = new(); - foreach (T elem in collection) + using var e = collection.GetEnumerator(); + if(e.MoveNext()) + builder.Append(e.Current); + while (e.MoveNext()) + { + builder.Append(separator); + builder.Append(e.Current); + } + return builder.ToString(); + } + + public static string MergeToString(this IEnumerable collection) + { + StringBuilder builder = new(); + foreach (var elem in collection) builder.Append(elem); return builder.ToString(); } diff --git a/DTLib/Filesystem/File.cs b/DTLib/Filesystem/File.cs index 8ed8912..85b58ee 100644 --- a/DTLib/Filesystem/File.cs +++ b/DTLib/Filesystem/File.cs @@ -3,7 +3,7 @@ namespace DTLib.Filesystem; public static class File { - public static int GetSize(string file) => new System.IO.FileInfo(file).Length.ToInt(); + public static long GetSize(string file) => new System.IO.FileInfo(file).Length; public static bool Exists(string file) => System.IO.File.Exists(file); @@ -32,9 +32,10 @@ public static class File public static byte[] ReadAllBytes(string file) { using System.IO.FileStream stream = OpenRead(file); - int size = GetSize(file); + int size = GetSize(file).ToInt(); byte[] output = new byte[size]; - stream.Read(output, 0, size); + if (stream.Read(output, 0, size) < size) + throw new Exception("can't read all bytes"); stream.Close(); return output; } diff --git a/DTLib/Filesystem/New/Directory.cs b/DTLib/Filesystem/New/Directory.cs new file mode 100644 index 0000000..bb2a280 --- /dev/null +++ b/DTLib/Filesystem/New/Directory.cs @@ -0,0 +1,120 @@ +namespace DTLib.Filesystem.New; + +public static class Directory +{ + public static bool Exists(string dir) => System.IO.Directory.Exists(dir); + + // создает папку, если её не существует + public static void Create(string dir) + { + if (!Exists(dir)) + { + // проверяет существование папки, в которой нужно создать dir + if (dir.Contains(Путь.Разд) && !Exists(dir.Remove(dir.LastIndexOf(Путь.Разд)))) + Create(dir.Remove(dir.LastIndexOf(Путь.Разд))); + System.IO.Directory.CreateDirectory(dir); + } + } + // копирует все файлы и папки + public static void Copy(string source_dir, string new_dir, bool owerwrite = false) + { + Create(new_dir); + var subdirs = new List(); + List files = GetAllFiles(source_dir, ref subdirs); + for (int i = 0; i < subdirs.Count; i++) + Create(subdirs[i].Replace(source_dir, new_dir)); + for (int i = 0; i < files.Count; i++) + File.Copy(files[i], files[i].Replace(source_dir, new_dir), owerwrite); + } + + // копирует все файлы и папки и выдаёт список конфликтующих файлов + public static void Copy(string source_dir, string new_dir, out List conflicts, bool owerwrite = false) + { + conflicts = new List(); + var subdirs = new List(); + List files = GetAllFiles(source_dir, ref subdirs); + Create(new_dir); + for (int i = 0; i < subdirs.Count; i++) + Create(subdirs[i].Replace(source_dir, new_dir)); + for (int i = 0; i < files.Count; i++) + { + string newfile = files[i].Replace(source_dir, new_dir); + if (File.Exists(newfile)) + conflicts.Add(newfile); + File.Copy(files[i], newfile, owerwrite); + } + } + + // удаляет папку со всеми подпапками и файлами + public static void Delete(string dir) + { + var subdirs = new List(); + List files = GetAllFiles(dir, ref subdirs); + for (int i = 0; i < files.Count; i++) + File.Delete(files[i]); + for (int i = subdirs.Count - 1; i >= 0; i--) + { + Log($"deleting {subdirs[i]}"); + if (Exists(subdirs[i])) + System.IO.Directory.Delete(subdirs[i], true); + } + Log($"deleting {dir}"); + if (Exists(dir)) + System.IO.Directory.Delete(dir, true); + } + + public static string[] GetFiles(string dir) => System.IO.Directory.GetFiles(dir); + public static string[] GetFiles(string dir, string searchPattern) => System.IO.Directory.GetFiles(dir, searchPattern); + public static string[] GetDirectories(string dir) => System.IO.Directory.GetDirectories(dir); + + // выдает список всех файлов + public static List GetAllFiles(string dir) + { + var all_files = new List(); + string[] cur_files = GetFiles(dir); + for (int i = 0; i < cur_files.Length; i++) + all_files.Add(cur_files[i]); + string[] cur_subdirs = GetDirectories(dir); + for (int i = 0; i < cur_subdirs.Length; i++) + all_files.AddRange(GetAllFiles(cur_subdirs[i])); + return all_files; + } + + // выдает список всех файлов и подпапок в папке + public static List GetAllFiles(string dir, ref List all_subdirs) + { + var all_files = new List(); + string[] cur_files = GetFiles(dir); + for (int i = 0; i < cur_files.Length; i++) + all_files.Add(cur_files[i]); + string[] cur_subdirs = GetDirectories(dir); + for (int i = 0; i < cur_subdirs.Length; i++) + { + all_subdirs.Add(cur_subdirs[i]); + all_files.AddRange(GetAllFiles(cur_subdirs[i], ref all_subdirs)); + } + return all_files; + } + + public static string GetCurrent() => System.IO.Directory.GetCurrentDirectory(); + + public static void CreateSymlink(string sourceName, string symlinkName) + { + if (symlinkName.Contains(Путь.Разд)) + Create(symlinkName.Remove(symlinkName.LastIndexOf(Путь.Разд))); + if (!Symlink.CreateSymbolicLink(symlinkName, sourceName, Symlink.SymlinkTarget.Directory)) + throw new InvalidOperationException($"some error occured while creating symlink\nDirectory.CreateSymlink({symlinkName}, {sourceName})"); + } + + // copies directory with symlinks instead of files + public static int SymCopy(string srcdir, string newdir) + { + List files = GetAllFiles(srcdir); + if (!srcdir.EndsWith(Путь.Разд)) srcdir += Путь.Разд; + if (!newdir.EndsWith(Путь.Разд)) newdir += Путь.Разд; + int i = 0; + for (; i < files.Count; i++) + File.CreateSymlink(files[i], files[i].Replace(srcdir, newdir)); + return i; + } +} diff --git a/DTLib/Filesystem/New/File.cs b/DTLib/Filesystem/New/File.cs new file mode 100644 index 0000000..cd8274a --- /dev/null +++ b/DTLib/Filesystem/New/File.cs @@ -0,0 +1,62 @@ +using System.IO; + +namespace DTLib.Filesystem.New; + +public class File +{ + public enum FileOpenMode + { + // open a file for reading + Read=1, + // (re)create a file for writing + Write=2, + // opens file for writing additional data to the end / creates new file + Append=4, + // (re)creates file for reading/writing + ReadWrite=Read|Write, + // opens file for readng/writing additional data to the end / creates new file + ReadAppend=Read|Append + } + + public readonly FileOpenMode Mode; + public readonly FileStream Stream; + public string Name; + + public File(string path, FileOpenMode mode) + { + if(!Exists(path)) + { + if (mode == FileOpenMode.Read) + throw new Exception($"file <{path}> is not found"); + } + Mode = mode; + Stream = mode switch + { + FileOpenMode.Read => System.IO.File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), + FileOpenMode.Write => System.IO.File.Open(path, FileMode.Open, FileAccess.Write, FileShare.ReadWrite), + FileOpenMode.Append => System.IO.File.Open(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite), + FileOpenMode.ReadWrite => System.IO.File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite), + FileOpenMode.ReadAppend => System.IO.File.Open(path, FileMode.Append, FileAccess.ReadWrite, FileShare.ReadWrite), + _ => throw new Exception($"unknown file mode: {mode}") + }; + } + + public static bool Exists(string path) => System.IO.File.Exists(path); + + public static void Create(string path) + { + if (Exists(path)) + throw new Exception($"file <{path} already exists"); + int sepIndex = path.LastIndexOf(Path.Sep); + if (sepIndex>-1) + Directory.Create(path.Remove(sepIndex)); + System.IO.File.Create(path).Close(); + } + + public static void Delete(string path) => System.IO.File.Delete(path); + + public void Delete(string path) + { + + } +} \ No newline at end of file diff --git a/DTLib/Filesystem/New/Path.cs b/DTLib/Filesystem/New/Path.cs new file mode 100644 index 0000000..149892d --- /dev/null +++ b/DTLib/Filesystem/New/Path.cs @@ -0,0 +1,39 @@ +using System.Runtime.CompilerServices; + +namespace DTLib.Filesystem.New; + +public static class Path +{ + + public static readonly char Sep = Environment.OSVersion.Platform == PlatformID.Win32NT ? '\\' : '/'; + private static readonly char NotSep = Environment.OSVersion.Platform == PlatformID.Win32NT ? '/' : '\\' ; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string Concat(string path, string addition) => $"{path}{Sep}{addition}"; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string Concat(params string[] parts) => StringConverter.MergeToString(Sep, parts); + + public static string FixSeparators(string path) + { + var chars = path.ToCharArray(); + int length = path.Length; + for(int i=0; i FixSeparators(Concat(parts)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string Resolve(string path, string addition) => FixSeparators(Concat(path, addition)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfEscapes(string path) + { + if (path.Contains("..")) + throw new Exception($"path <{path}> uses <..>, that's not allowed"); + } +} \ No newline at end of file