From fe980d5a82382a6e9adf371a51fb77fb662ef88c Mon Sep 17 00:00:00 2001 From: Timerix22 Date: Tue, 7 Feb 2023 19:40:00 +0600 Subject: [PATCH] contining file io rewok --- DTLib.Tests/DTLib.Tests.csproj | 2 +- DTLib.Tests/Program.cs | 12 +++ DTLib/Console/LaunchArgumentParser.cs | 3 +- DTLib/DTLib.csproj | 2 +- DTLib/Experimental/Reactive/ReactiveStream.cs | 4 +- DTLib/Extensions/BaseConverter.cs | 8 +- DTLib/Extensions/SpanHelper.cs | 2 +- DTLib/Filesystem/Directory.cs | 97 ++++++++++++------- DTLib/Filesystem/File.cs | 55 +++++++---- DTLib/Filesystem/Path.cs | 64 +++++++++++- DTLib/Hasher.cs | 2 - DTLib/XXHash.cs | 15 ++- 12 files changed, 190 insertions(+), 76 deletions(-) diff --git a/DTLib.Tests/DTLib.Tests.csproj b/DTLib.Tests/DTLib.Tests.csproj index 3b2c8ac..7ab9453 100644 --- a/DTLib.Tests/DTLib.Tests.csproj +++ b/DTLib.Tests/DTLib.Tests.csproj @@ -27,7 +27,7 @@ - + diff --git a/DTLib.Tests/Program.cs b/DTLib.Tests/Program.cs index d058ea8..eff8654 100644 --- a/DTLib.Tests/Program.cs +++ b/DTLib.Tests/Program.cs @@ -30,6 +30,18 @@ public static class Program try { + string path = "file"; + string path2 = path + "_temp"; + // Ensure that the target does not exist. + File.Delete(path2); + // Copy the file. + File.Copy(path, path2); + System.Console.WriteLine("{0} was copied to {1}.", path, path2); + // Delete the newly created file. + File.Delete(path2); + System.Console.WriteLine("{0} was successfully deleted.", path2); + return; + new LaunchArgumentParser().WithNoExit().ParseAndHandle(args); TestPInvoke.TestAll(); TestAutoarr.TestAll(); diff --git a/DTLib/Console/LaunchArgumentParser.cs b/DTLib/Console/LaunchArgumentParser.cs index 09ef953..14b3bd8 100644 --- a/DTLib/Console/LaunchArgumentParser.cs +++ b/DTLib/Console/LaunchArgumentParser.cs @@ -108,7 +108,8 @@ public class LaunchArgumentParser if (i+1 >= args.Length) throw new Exception($"argument <{args[i]}> should have a parameter after it"); i++; // next arg - arg.Handler = () => arg.HandlerWithArg(args[i]); + var i1 = i; + arg.Handler = () => arg.HandlerWithArg(args[i1]); } else if (arg.Handler is null) throw new NullReferenceException($"argument <{args[i]}> hasn't got any handlers"); diff --git a/DTLib/DTLib.csproj b/DTLib/DTLib.csproj index 48b76c8..6519210 100644 --- a/DTLib/DTLib.csproj +++ b/DTLib/DTLib.csproj @@ -2,7 +2,7 @@ DTLib - 1.0.4 + 1.0.5 Timerix Library for all my C# projects GIT diff --git a/DTLib/Experimental/Reactive/ReactiveStream.cs b/DTLib/Experimental/Reactive/ReactiveStream.cs index 0c95923..0021cdc 100644 --- a/DTLib/Experimental/Reactive/ReactiveStream.cs +++ b/DTLib/Experimental/Reactive/ReactiveStream.cs @@ -1,9 +1,7 @@ namespace DTLib.Experimental.Reactive { - public class ReactiveStream : IEnumerable>, IList> + public class ReactiveStream : IList> { - public ReactiveStream() { } - List> _storage = new(); List> Storage { diff --git a/DTLib/Extensions/BaseConverter.cs b/DTLib/Extensions/BaseConverter.cs index 297140f..418f86d 100644 --- a/DTLib/Extensions/BaseConverter.cs +++ b/DTLib/Extensions/BaseConverter.cs @@ -24,12 +24,12 @@ public static class BaseConverter public static uint ToUInt(this T input) => Convert.ToUInt32(input); public static long ToLong(this T input) => Convert.ToInt64(input); public static ulong ToULong(this T input) => Convert.ToUInt64(input); - public static float ToFloat(this string input) => float.Parse(input, NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + public static float ToFloat(this string input) => float.Parse(input, NumberStyles.Any, CultureInfo.InvariantCulture); #if NETSTANDARD2_1 || NET6_0 || NET7_0 || NET8_0 - public static float ToFloat(this ReadOnlySpan input) => float.Parse(input, NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + public static float ToFloat(this ReadOnlySpan input) => float.Parse(input, NumberStyles.Any, CultureInfo.InvariantCulture); #endif - public static double ToDouble(this T input) => Convert.ToDouble(input, System.Globalization.CultureInfo.InvariantCulture); - public static decimal ToDecimal(this T input) => Convert.ToDecimal(input, System.Globalization.CultureInfo.InvariantCulture); + public static double ToDouble(this T input) => Convert.ToDouble(input, CultureInfo.InvariantCulture); + public static decimal ToDecimal(this T input) => Convert.ToDecimal(input, CultureInfo.InvariantCulture); public static int ToInt(this byte[] bytes) { diff --git a/DTLib/Extensions/SpanHelper.cs b/DTLib/Extensions/SpanHelper.cs index 6a3fbeb..72cb4de 100644 --- a/DTLib/Extensions/SpanHelper.cs +++ b/DTLib/Extensions/SpanHelper.cs @@ -1,6 +1,6 @@ +#if NETSTANDARD2_1 || NET6_0 || NET7_0 || NET8_0 namespace DTLib.Extensions; -#if NETSTANDARD2_1 || NET6_0 || NET7_0 || NET8_0 public static class SpanHelper { public static ReadOnlySpan After(this ReadOnlySpan span, T c) where T : IEquatable diff --git a/DTLib/Filesystem/Directory.cs b/DTLib/Filesystem/Directory.cs index e446d4d..c2fc351 100644 --- a/DTLib/Filesystem/Directory.cs +++ b/DTLib/Filesystem/Directory.cs @@ -2,56 +2,85 @@ public static class Directory { - public static bool Exists(string dir) => System.IO.Directory.Exists(Path.FixSeparators(dir)); + public static bool Exists(string dir, bool separatorsFixed) + { + if(!separatorsFixed) + dir = Path.FixSeparators(dir); + return System.IO.Directory.Exists(dir); + } /// создает папку, если её не существует - public static void Create(string dir) + public static void Create(string dir, bool separatorsFixed) { - dir = Path.FixSeparators(dir); + if(!separatorsFixed) + dir = Path.FixSeparators(dir); if (!Exists(dir)) { // проверяет существование папки, в которой нужно создать dir - if (dir.Contains(Path.Sep) && !Exists(dir.Remove(dir.LastIndexOf(Path.Sep)))) - Create(dir.Remove(dir.LastIndexOf(Path.Sep))); - System.IO.Directory.CreateDirectory(dir); + if (dir.Contains(Path.Sep)) + { + string parentDir = dir.Remove(dir.LastIndexOf(Path.Sep)); + if(!Exists(parentDir,true)) + Create(parentDir,true); + } + else System.IO.Directory.CreateDirectory(dir); } } /// копирует все файлы и папки - public static void Copy(string source_dir, string new_dir, bool owerwrite = false) + public static void Copy(string source_dir, string new_dir, bool owerwrite) { - 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); + Copy_internal(source_dir, new_dir, owerwrite, null); } /// копирует все файлы и папки и выдаёт список конфликтующих файлов - public static void Copy(string source_dir, string new_dir, out List conflicts, bool owerwrite = false) + public static void Copy(string source_dir, string new_dir, bool owerwrite, out List conflicts) { conflicts = new List(); - var subdirs = new List(); - List files = GetAllFiles(source_dir, ref subdirs); + Copy_internal(source_dir, new_dir, owerwrite, conflicts); + } + + private static void Copy_internal(string source_dir, string new_dir, bool owerwrite, List conflicts) + { + bool countConflicts = conflicts is null; + List files = GetAllFiles(source_dir); 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); + string newfile = Path.ReplaceBase(files[i], source_dir, new_dir); + if (countConflicts && File.Exists(newfile)) + conflicts!.Add(newfile); File.Copy(files[i], newfile, owerwrite); } } /// удаляет папку со всеми подпапками и файлами - public static void Delete(string dir) => System.IO.Directory.Delete(Path.FixSeparators(dir), true); + public static void Delete(string dir, bool separatorsFixed) + { + if(!separatorsFixed) + dir = Path.FixSeparators(dir); + System.IO.Directory.Delete(dir, true); + } - public static string[] GetFiles(string dir) => System.IO.Directory.GetFiles(Path.FixSeparators(dir)); - public static string[] GetFiles(string dir, string searchPattern) => System.IO.Directory.GetFiles(Path.FixSeparators(dir), searchPattern); - public static string[] GetDirectories(string dir) => System.IO.Directory.GetDirectories(Path.FixSeparators(dir)); + public static string[] GetFiles(string dir, bool separatorsFixed) + { + if (!separatorsFixed) + dir = Path.FixSeparators(dir); + return System.IO.Directory.GetFiles(dir); + } + + public static string[] GetFiles(string dir, string searchPattern, bool separatorsFixed) + { + if (!separatorsFixed) + dir = Path.FixSeparators(dir); + return System.IO.Directory.GetFiles(dir, searchPattern); + } + + public static string[] GetDirectories(string dir, bool separatorsFixed) + { + if (!separatorsFixed) + dir = Path.FixSeparators(dir); + return System.IO.Directory.GetDirectories(dir); + } /// выдает список всех файлов public static List GetAllFiles(string dir) @@ -84,13 +113,15 @@ public static class Directory public static string GetCurrent() => System.IO.Directory.GetCurrentDirectory(); - public static void CreateSymlink(string sourceName, string symlinkName) + public static void CreateSymlink(string sourcePath, string symlinkPath, bool separatorsFixed) { - sourceName = Path.FixSeparators(sourceName); - symlinkName = Path.FixSeparators(symlinkName); - if (symlinkName.Contains(Path.Sep)) - Create(symlinkName.Remove(symlinkName.LastIndexOf(Path.Sep))); - if (!Symlink.CreateSymbolicLink(symlinkName, sourceName, Symlink.SymlinkTarget.Directory)) - throw new InvalidOperationException($"some error occured while creating symlink\nDirectory.CreateSymlink({symlinkName}, {sourceName})"); + if (!separatorsFixed) + { + sourcePath = Path.FixSeparators(sourcePath); + symlinkPath = Path.FixSeparators(symlinkPath); + } + Create(Path.ParentDir(symlinkPath, true), true); + if (!Symlink.CreateSymbolicLink(symlinkPath, sourcePath, Symlink.SymlinkTarget.Directory)) + throw new InvalidOperationException($"some error occured while creating symlink\nDirectory.CreateSymlink({symlinkPath}, {sourcePath})"); } } diff --git a/DTLib/Filesystem/File.cs b/DTLib/Filesystem/File.cs index 4a107a7..ad1a26c 100644 --- a/DTLib/Filesystem/File.cs +++ b/DTLib/Filesystem/File.cs @@ -1,33 +1,55 @@ - -namespace DTLib.Filesystem; +namespace DTLib.Filesystem; public static class File { /// возвращает размер файла в байтах - public static long GetSize(string file) => new System.IO.FileInfo(Path.FixSeparators(file)).Length; + public static long GetSize(string file, bool separatorsFixed) + { + if (!separatorsFixed) + file = Path.FixSeparators(file); + return new System.IO.FileInfo(file).Length; + } - public static bool Exists(string file) => System.IO.File.Exists(Path.FixSeparators(file)); + public static bool Exists(string file, bool separatorsFixed) + { + if (!separatorsFixed) + file = Path.FixSeparators(file); + return System.IO.File.Exists(file); + } /// если файл не существует, создаёт файл с папками из его пути и закрывает этот фвйл - public static void Create(string file) + public static void Create(string file, bool separatorsFixed) { - file = Path.FixSeparators(file); - if (!Exists(file)) + if (!separatorsFixed) + file = Path.FixSeparators(file); + if (!Exists(file, true)) { - if (file.Contains(Path.Sep)) - Directory.Create(file.Remove(file.LastIndexOf(Path.Sep))); + Directory.Create(Path.ParentDir(file, true), true); using System.IO.FileStream stream = System.IO.File.Create(file); stream.Close(); } } - public static void Copy(string srcPath, string newPath, bool overwrite = false) + public static void Copy(string srcPath, string newPath, bool overwrite = false, bool separatorsFixed) { - srcPath = Path.FixSeparators(srcPath); - newPath = Path.FixSeparators(newPath); - if (!overwrite && Exists(newPath)) - throw new Exception($"file <{newPath}> alredy exists"); - System.IO.File.Copy(srcPath, newPath, overwrite); + if (!separatorsFixed) + { + srcPath = Path.FixSeparators(srcPath); + newPath = Path.FixSeparators(newPath); + } + + if (Exists(newPath)) + { + if(overwrite) System.IO.File.Delete(newPath); + else throw new Exception($"file <{newPath}> alredy exists"); + } + else Directory.Create(Path.ParentDir(newPath, true)); + using var srcFile=System.IO.File.Open(srcPath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite); + using var newFile=System.IO.File.Open(newPath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite); + srcFile.CopyTo(newFile); + srcFile.Close(); + newFile.Flush(); + newFile.Close(); } public static void Delete(string file) => System.IO.File.Delete(Path.FixSeparators(file)); @@ -70,8 +92,7 @@ public static class File { file = Path.FixSeparators(file); if (Exists(file)) - return System.IO.File.Open(file, System.IO.FileMode.Open, System.IO.FileAccess.Read, - System.IO.FileShare.ReadWrite); + return System.IO.File.Open(file, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite); throw new Exception($"file not found: <{file}>"); } diff --git a/DTLib/Filesystem/Path.cs b/DTLib/Filesystem/Path.cs index 864fd4e..9fa8620 100644 --- a/DTLib/Filesystem/Path.cs +++ b/DTLib/Filesystem/Path.cs @@ -8,11 +8,30 @@ public static class Path public static readonly char Sep = Environment.OSVersion.Platform == PlatformID.Win32NT ? '\\' : '/'; private static readonly char NotSep = Environment.OSVersion.Platform == PlatformID.Win32NT ? '/' : '\\' ; + /// does not correct separators, use Resolve for correction + /// [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 Concat(string path, string addition) + { + if (!path.EndsWith(Sep) && !addition.StartsWith(Sep)) + path += Sep; + return path + addition; + } + + /// + public static string Concat(params string[] parts) + { + StringBuilder builder = new StringBuilder(); + builder.Append(parts[0]); + for (int i = 1; i < parts.Length; i++) + { + char lastC = builder[builder.Length - 1]; + if(lastC!=Sep && lastC!=NotSep) + builder.Append(Sep); + builder.Append(parts[i]); + } + return builder.ToString(); + } public static string FixSeparators(string path) { @@ -21,7 +40,7 @@ public static class Path for(int i=0; i doesnt starts with <{baseDir}"); + return Concat(otherDir, path.Substring(baseDir.Length)); + } } \ No newline at end of file diff --git a/DTLib/Hasher.cs b/DTLib/Hasher.cs index 204e28b..ac200da 100644 --- a/DTLib/Hasher.cs +++ b/DTLib/Hasher.cs @@ -10,8 +10,6 @@ public class Hasher readonly HashAlgorithm sha256 = SHA256.Create(); readonly HashAlgorithm xxh32 = XXHash32.Create(); - public Hasher() { } - // хеш массива public byte[] Hash(byte[] input) => sha256.ComputeHash(input); diff --git a/DTLib/XXHash.cs b/DTLib/XXHash.cs index c232ffd..9d081ec 100644 --- a/DTLib/XXHash.cs +++ b/DTLib/XXHash.cs @@ -27,7 +27,7 @@ sealed class XXHash32 : HashAlgorithm { if (BitConverter.IsLittleEndian) { - FuncGetLittleEndianUInt32 = new Func((x, i) => + FuncGetLittleEndianUInt32 = (x, i) => { unsafe { @@ -36,12 +36,12 @@ sealed class XXHash32 : HashAlgorithm return *(uint*)(array + i); } } - }); - FuncGetFinalHashUInt32 = new Func(i => (i & 0x000000FFU) << 24 | (i & 0x0000FF00U) << 8 | (i & 0x00FF0000U) >> 8 | (i & 0xFF000000U) >> 24); + }; + FuncGetFinalHashUInt32 = i => (i & 0x000000FFU) << 24 | (i & 0x0000FF00U) << 8 | (i & 0x00FF0000U) >> 8 | (i & 0xFF000000U) >> 24; } else { - FuncGetLittleEndianUInt32 = new Func((x, i) => + FuncGetLittleEndianUInt32 = (x, i) => { unsafe { @@ -50,8 +50,8 @@ sealed class XXHash32 : HashAlgorithm return (uint)(array[i++] | (array[i++] << 8) | (array[i++] << 16) | (array[i] << 24)); } } - }); - FuncGetFinalHashUInt32 = new Func(i => i); + }; + FuncGetFinalHashUInt32 = i => i; } } @@ -102,8 +102,7 @@ sealed class XXHash32 : HashAlgorithm /// The number of bytes in the byte array to use as data. protected override void HashCore(byte[] array, int ibStart, int cbSize) { - if (State != 1) - State = 1; + State = 1; int size = cbSize - ibStart; _RemainingLength = size & 15; if (cbSize >= 16)