From 0513b9fddaee0dc67c60f32a9a87b73b985e11fb Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 23 Mar 2023 18:44:08 +0300 Subject: [PATCH 01/12] =?UTF-8?q?=D0=B0=D1=80=D1=85=D0=B8=D0=B2=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20+=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D0=B0=D1=80=D1=85=D0=B8=D0=B2=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LZW/LZW.sln | 25 ++++ LZW/LZW/Bor.cs | 113 ++++++++++++++++++ LZW/LZW/LZW.cs | 285 +++++++++++++++++++++++++++++++++++++++++++++ LZW/LZW/LZW.csproj | 10 ++ LZW/LZW/Program.cs | 17 +++ 5 files changed, 450 insertions(+) create mode 100644 LZW/LZW.sln create mode 100644 LZW/LZW/Bor.cs create mode 100644 LZW/LZW/LZW.cs create mode 100644 LZW/LZW/LZW.csproj create mode 100644 LZW/LZW/Program.cs diff --git a/LZW/LZW.sln b/LZW/LZW.sln new file mode 100644 index 0000000..2c0fa40 --- /dev/null +++ b/LZW/LZW.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33403.182 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LZW", "LZW\LZW.csproj", "{B99BFF18-B071-406A-989E-994845F53D3B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B99BFF18-B071-406A-989E-994845F53D3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B99BFF18-B071-406A-989E-994845F53D3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B99BFF18-B071-406A-989E-994845F53D3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B99BFF18-B071-406A-989E-994845F53D3B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {40032E74-4213-49E7-9C40-632CA5D1FA92} + EndGlobalSection +EndGlobal diff --git a/LZW/LZW/Bor.cs b/LZW/LZW/Bor.cs new file mode 100644 index 0000000..307bade --- /dev/null +++ b/LZW/LZW/Bor.cs @@ -0,0 +1,113 @@ +namespace LZW; + +// A container for storing strings, in the form of a suspended tree +public class Bor +{ + private BorElement root = new BorElement(); + + // Adding an element + public (bool, int) Add(Bor bor, char[] buffer, int from, int to) + { + if (root == null || buffer == null) + { + throw new InvalidOperationException(); + } + var walker = root; + int i = 0; + int pointer = from; + int toFlow = -1; + bool isStringInBor = bor.Contains(buffer, from, to); + while (i < to - from + 1) + { + int number = (int)buffer[pointer]; + if (!walker.Next.ContainsKey(number)) + { + walker.Next.Add(number, new BorElement()); + ++walker.SizeDictionary; + } + if (!isStringInBor) + { + ++walker.Next[number].HowManyStringInDictionary; + } + toFlow = walker.Flow; + walker = walker.Next[number]; + pointer++; + i++; + } + if (walker.IsTerminal == false) + { + walker.Flow = root.HowManyStringInDictionary; + root.HowManyStringInDictionary++; + } + + return walker.IsTerminal == false ? (walker.IsTerminal = true && true, toFlow) : (false, toFlow); + } + + public int ReturnFlowByCharArray(char[] buffer, int to, int from) + { + var walker = root; + int i = 0; + int pointer = from; + while(i < to - from + 1) + { + int number = (int)buffer[pointer]; + if (!walker.Next.ContainsKey(number)) + { + return -1; + } + walker = walker.Next[number]; + ++i; + } + return walker.Flow; + } + + public int HowManyStringsInBor() + { + if (root == null) + { + return -1; + } + return root.HowManyStringInDictionary; + } + + // Checks for the presence of a string + public bool Contains(char[] buffer, int from, int to) + { + if (root == null) + { + return false; + } + var walker = root; + int i = 0; + int pointer = from; + while (i < to - from + 1) + { + if (!walker.Next.ContainsKey(buffer[pointer])) + { + return false; + } + walker = walker.Next[buffer[pointer]]; + pointer++; + ++i; + } + return true; + } + + private class BorElement + { + public Dictionary Next { get; set; } + public bool IsTerminal { get; set; } + + public int SizeDictionary { get; set; } + + public int HowManyStringInDictionary { get; set; } + + public int Flow { get; set; } + + public BorElement() + { + Next = new Dictionary(); + Flow = -1; + } + } +} diff --git a/LZW/LZW/LZW.cs b/LZW/LZW/LZW.cs new file mode 100644 index 0000000..f4a83c6 --- /dev/null +++ b/LZW/LZW/LZW.cs @@ -0,0 +1,285 @@ +using System; +using System.IO; +using System.Text; + +namespace LZW; + +public class LZW +{ + private bool ChangeFileNameToTxt(ref char[] newFile) + { + if (newFile.Length < 8) + { + return false; + } + if (newFile[newFile.Length - 1] == 'd' + && newFile[newFile.Length - 2] == 'e' + && newFile[newFile.Length - 3] == 'p' + && newFile[newFile.Length - 4] == 'p' + && newFile[newFile.Length - 5] == 'i' + && newFile[newFile.Length - 6] == 'z' + && newFile[newFile.Length - 7] == '.') + { + Array.Resize(ref newFile, newFile.Length - 3); + newFile[newFile.Length - 1] = 't'; + newFile[newFile.Length - 2] = 'x'; + newFile[newFile.Length - 3] = 't'; + return true; + } + else + { + return false; + } + } + + private bool ChangeFileNameToZipped(ref char[] newFile) + { + if (newFile.Length < 5) + { + return false; + } + if (newFile[newFile.Length - 1] == 't' + && newFile[newFile.Length - 2] == 'x' + && newFile[newFile.Length - 3] == 't' + && newFile[newFile.Length - 4] == '.' + || newFile[newFile.Length - 1] == 'e' + && newFile[newFile.Length - 2] == 'x' + && newFile[newFile.Length - 3] == 'e' + && newFile[newFile.Length - 4] == '.') + { + Array.Resize(ref newFile, newFile.Length + 3); + newFile[newFile.Length - 1] = 'd'; + newFile[newFile.Length - 2] = 'e'; + newFile[newFile.Length - 3] = 'p'; + newFile[newFile.Length - 4] = 'p'; + newFile[newFile.Length - 5] = 'i'; + newFile[newFile.Length - 6] = 'z'; + return true; + } + else + { + return false; + } + } + + private bool CodeFile(string fileName) + { + char[] newFileArray = new char[fileName.Length]; + Array.Copy(fileName.ToCharArray(), newFileArray, fileName.Length); + bool isCorrect = ChangeFileNameToZipped(ref newFileArray); + if (!isCorrect) + { + return false; + } + string? newFile = new string(newFileArray); + if (newFile == null) + { + return false; + } + File.WriteAllText(newFile.ToString(), string.Empty); + + // Запись алфавита в бор + byte[] bufferIn = File.ReadAllBytes(fileName); + int j = 0; + char[] textFromFile = new char[bufferIn.Length]; + char[] firstAddedAlphabet = new char[bufferIn.Length]; + var fakeBor = new Bor(); + var bor = new Bor(); + int pointer = 0; + for (byte i = 0; i < bufferIn.Length; ++i) + { + textFromFile[j] = Convert.ToChar(bufferIn[i]); + var (isFirstAdded, _) = bor.Add(bor, textFromFile, j, j); + var (_, _) = fakeBor.Add(bor, textFromFile, j, j); + if (isFirstAdded) + { + firstAddedAlphabet[pointer] = textFromFile[j]; + ++pointer; + } + ++j; + } + + // Проход LZW алгоритма по строке + int walker = 0; + for (int i = 0; i < textFromFile.Length; i++) + { + if (!bor.Contains(textFromFile, walker, i)) + { + var (_, _) = fakeBor.Add(bor, textFromFile, walker, i); + walker = i; + } + } + + int maxFlow = fakeBor.HowManyStringsInBor(); + fakeBor = null; + + // Добавление размера алфавита + символы + ' ' + Array.Resize(ref firstAddedAlphabet, pointer); + char[] alphabet = pointer.ToString().ToCharArray(); + int lastAlphabetSize = alphabet.Length; + char[] maxFlowArray = maxFlow.ToString().ToCharArray(); + Array.Resize(ref alphabet, pointer + alphabet.Length + 2 + maxFlowArray.Length); + alphabet[lastAlphabetSize] = ' '; + int p = 0; + int l = lastAlphabetSize + 1; + while (p < maxFlowArray.Length) + { + alphabet[l] = maxFlowArray[p]; + ++l; + ++p; + } + alphabet[l] = ' '; + ++l; + for (int k = 0; k < firstAddedAlphabet.Length; ++k) + { + alphabet[l] = firstAddedAlphabet[k]; + ++l; + } + + // Запись алфавита + var filestream = new FileStream(newFile, FileMode.OpenOrCreate); + StreamWriter filestreamwriter = new StreamWriter(filestream); + filestreamwriter.Write(alphabet, 0, alphabet.Length); + filestreamwriter.Close(); + filestream.Close(); + + // Добавление потоков в файл + walker = 0; + for (int i = 0; i < textFromFile.Length; i++) + { + if (!bor.Contains(textFromFile, walker, i)) + { + var (_, flow) = bor.Add(bor, textFromFile, walker, i); + walker = i; + var bufferOut = new byte[maxFlow]; + byte[] bytes = BitConverter.GetBytes(flow); + for (int t = 0; t < bytes.Length; ++t) + { + bufferOut[t] = bytes[t]; + } + var fstreamNew = new FileStream(newFile.ToString(), FileMode.Append); + fstreamNew.WriteAsync(bufferOut, 0, bufferOut.Length); + fstreamNew.Close(); + } + } + + // Добавление последнего потока в файл + var flowLast = bor.ReturnFlowByCharArray(textFromFile, bufferIn.Length - 1, bufferIn.Length - 1); + var bufferOutLast = new byte[maxFlow]; + byte[] bytesLast = BitConverter.GetBytes(flowLast); + for (int t = 0; t < bytesLast.Length; ++t) + { + bufferOutLast[t] = bytesLast[t]; + } + var LastFstreamNew = new FileStream(newFile.ToString(), FileMode.Append); + LastFstreamNew.WriteAsync(bufferOutLast, 0, bufferOutLast.Length); + LastFstreamNew.Close(); + return true; + } + + private bool DecodeFile(string fileName) + { + byte[] bufferIn = File.ReadAllBytes(fileName); + char[] stringWithCodes = Encoding.UTF8.GetString(bufferIn).ToCharArray(); + int k = 1; + int sizeAlphabet = 0; + int i = 0; + char[] newFileArray = new char[fileName.Length]; + Array.Copy(fileName.ToCharArray(), newFileArray, fileName.Length); + bool isCorrect = ChangeFileNameToTxt(ref newFileArray); + if (!isCorrect) + { + return false; + } + string? newFile = new string(newFileArray); + if (newFile == null) + { + return false; + } + + File.WriteAllText(newFile, string.Empty); + + while (stringWithCodes[i] != 32) + { + sizeAlphabet = sizeAlphabet * k + stringWithCodes[i] - 48; + k = 10; + ++i; + } + ++i; + int sizeSymbols = 0; + k = 1; + while (stringWithCodes[i] != 32) + { + sizeSymbols = sizeSymbols * k + stringWithCodes[i] - 48; + k = 10; + ++i; + } + ++i; + var dictionaryForDecode = new Dictionary(); + int sizeFromToInBufferIn = i + sizeAlphabet; + int index = 0; + for(; i < sizeFromToInBufferIn; ++i) + { + dictionaryForDecode.Add(index, ((char)bufferIn[i]).ToString()); + index++; + } + + int input = 0; + StringBuilder? previousString = null; + bool isFirst = true; + while (i < bufferIn.Length) + { + + var symbolFromArray = new byte[sizeSymbols]; + int pointerForSymbolsFromOneArray = 0; + int size = i + sizeSymbols; + for( ; i < size; ++i) + { + symbolFromArray[pointerForSymbolsFromOneArray] = bufferIn[i]; + ++pointerForSymbolsFromOneArray; + } + input = BitConverter.ToInt32(symbolFromArray, 0); + if (!isFirst) + { + if (!dictionaryForDecode.ContainsKey(input)) + { + previousString.Append(previousString[0]); + dictionaryForDecode.Add(index, previousString.ToString()); + } + var stringByIndex = dictionaryForDecode[input]; + if (index != input) + { + previousString.Append(stringByIndex[0]); + dictionaryForDecode.Add(index, previousString.ToString()); + } + File.AppendAllText(newFile, stringByIndex); + previousString = new StringBuilder(stringByIndex); + ++index; + } + else + { + var stringByIndex = dictionaryForDecode[input]; + previousString = new StringBuilder(stringByIndex); + isFirst = false; + File.AppendAllText(newFile, stringByIndex); + } + } + return true; + } + + public bool LzwAlgorithm(string fileName, string parametr) + { + if (parametr.Length == 2 && parametr[0] == '-' && parametr[1] == 'c') + { + return CodeFile(fileName); + } + else if (parametr.Length == 2 && parametr[0] == '-' && parametr[1] == 'u') + { + return DecodeFile(fileName); + } + else + { + return false; + } + } +} \ No newline at end of file diff --git a/LZW/LZW/LZW.csproj b/LZW/LZW/LZW.csproj new file mode 100644 index 0000000..f02677b --- /dev/null +++ b/LZW/LZW/LZW.csproj @@ -0,0 +1,10 @@ + + + + Exe + net7.0 + enable + enable + + + diff --git a/LZW/LZW/Program.cs b/LZW/LZW/Program.cs new file mode 100644 index 0000000..ab82493 --- /dev/null +++ b/LZW/LZW/Program.cs @@ -0,0 +1,17 @@ +namespace LZW; + +using System; + +class Program +{ + public static void Main(string[] args) + { + var lzw = new LZW(); + var isCorrect = lzw.LzwAlgorithm(args[0], args[1]); + if (!isCorrect) + { + Console.WriteLine("Problems..."); + return; + } + } +} \ No newline at end of file From f7cf014eed6daa015555bffa1fae58a8dfac7100 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 23 Mar 2023 18:59:53 +0300 Subject: [PATCH 02/12] =?UTF-8?q?+=D0=BA=D0=BE=D1=8D=D1=84=20=D1=81=D0=B6?= =?UTF-8?q?=D0=B0=D1=82=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LZW/LZW/LZW.cs | 17 ++++++++++++----- LZW/LZW/Program.cs | 3 ++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/LZW/LZW/LZW.cs b/LZW/LZW/LZW.cs index f4a83c6..eb5305c 100644 --- a/LZW/LZW/LZW.cs +++ b/LZW/LZW/LZW.cs @@ -62,10 +62,12 @@ private bool ChangeFileNameToZipped(ref char[] newFile) } } - private bool CodeFile(string fileName) + private bool CodeFile(string fileName, ref double compressionRatio) { char[] newFileArray = new char[fileName.Length]; Array.Copy(fileName.ToCharArray(), newFileArray, fileName.Length); + FileInfo file = new System.IO.FileInfo(fileName); + double sizeForCompressionRatio = file.Length; bool isCorrect = ChangeFileNameToZipped(ref newFileArray); if (!isCorrect) { @@ -174,6 +176,9 @@ private bool CodeFile(string fileName) var LastFstreamNew = new FileStream(newFile.ToString(), FileMode.Append); LastFstreamNew.WriteAsync(bufferOutLast, 0, bufferOutLast.Length); LastFstreamNew.Close(); + file = new System.IO.FileInfo(newFile.ToString()); + double newSizeForCompressionRatio = file.Length; + compressionRatio = newSizeForCompressionRatio / sizeForCompressionRatio; return true; } @@ -267,19 +272,21 @@ private bool DecodeFile(string fileName) return true; } - public bool LzwAlgorithm(string fileName, string parametr) + public (bool, double) LzwAlgorithm(string fileName, string parametr) { if (parametr.Length == 2 && parametr[0] == '-' && parametr[1] == 'c') { - return CodeFile(fileName); + double compressionRatio = 0; + var isCorrect = CodeFile(fileName, ref compressionRatio); + return (isCorrect, compressionRatio); } else if (parametr.Length == 2 && parametr[0] == '-' && parametr[1] == 'u') { - return DecodeFile(fileName); + return (DecodeFile(fileName), 0); } else { - return false; + return (false, 0); } } } \ No newline at end of file diff --git a/LZW/LZW/Program.cs b/LZW/LZW/Program.cs index ab82493..a0d1dcf 100644 --- a/LZW/LZW/Program.cs +++ b/LZW/LZW/Program.cs @@ -7,11 +7,12 @@ class Program public static void Main(string[] args) { var lzw = new LZW(); - var isCorrect = lzw.LzwAlgorithm(args[0], args[1]); + var (isCorrect, compressionRatio) = lzw.LzwAlgorithm(args[0], args[1]); if (!isCorrect) { Console.WriteLine("Problems..."); return; } + Console.WriteLine(compressionRatio); } } \ No newline at end of file From 975c5916286e39c44c32c098608476a4a4bf0a28 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 24 Mar 2023 11:04:14 +0300 Subject: [PATCH 03/12] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB,=20=D0=B4=D0=BE=20=D1=8D=D1=82=D0=BE=D0=B3=D0=BE?= =?UTF-8?q?=20=D0=BD=D0=B5=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5=20?= =?UTF-8?q?=D1=81=D0=B8=D0=BC=D0=B2=D0=BE=D0=BB=D1=8B=20=D0=BD=D0=B5=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D1=8B=D0=B2=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=D1=81=D1=8C=20=D0=BA=D0=B0=D0=BA=20=D0=BD=D0=B0=D0=B4=D0=BE,?= =?UTF-8?q?=20=D1=83=D0=B1=D1=80=D0=B0=D0=BB=20=D0=B8=D0=B7=20zipped=20?= =?UTF-8?q?=D1=84=D0=B0=D0=B9=D0=BB=D0=B0=20=D0=B7=D0=B0=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D1=8C=20=D0=B0=D0=BB=D1=84=D0=B0=D0=B2=D0=B8=D1=82=D0=B0,=20?= =?UTF-8?q?=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80=D0=B0=20=D0=B0=D0=BB=D1=84?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D1=82=D0=B0=20=D0=B8=20=D1=80=D0=B0=D0=B7?= =?UTF-8?q?=D0=BC=D0=B5=D1=80=20=D1=81=D0=B8=D0=BC=D0=B2=D0=BE=D0=BB=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LZW/LZW.sln | 8 ++- LZW/LZW/LZW.cs | 170 ++++++++++++++++----------------------------- LZW/LZW/Program.cs | 1 + 3 files changed, 66 insertions(+), 113 deletions(-) diff --git a/LZW/LZW.sln b/LZW/LZW.sln index 2c0fa40..5f47f6c 100644 --- a/LZW/LZW.sln +++ b/LZW/LZW.sln @@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.4.33403.182 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LZW", "LZW\LZW.csproj", "{B99BFF18-B071-406A-989E-994845F53D3B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LZW", "LZW\LZW.csproj", "{B99BFF18-B071-406A-989E-994845F53D3B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsForLZW", "TestsForLZW\TestsForLZW.csproj", "{C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,6 +17,10 @@ Global {B99BFF18-B071-406A-989E-994845F53D3B}.Debug|Any CPU.Build.0 = Debug|Any CPU {B99BFF18-B071-406A-989E-994845F53D3B}.Release|Any CPU.ActiveCfg = Release|Any CPU {B99BFF18-B071-406A-989E-994845F53D3B}.Release|Any CPU.Build.0 = Release|Any CPU + {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/LZW/LZW/LZW.cs b/LZW/LZW/LZW.cs index eb5305c..60c3e74 100644 --- a/LZW/LZW/LZW.cs +++ b/LZW/LZW/LZW.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.IO; using System.Text; @@ -12,7 +13,7 @@ private bool ChangeFileNameToTxt(ref char[] newFile) { return false; } - if (newFile[newFile.Length - 1] == 'd' + if (newFile[newFile.Length - 1] == 'd' && newFile[newFile.Length - 2] == 'e' && newFile[newFile.Length - 3] == 'p' && newFile[newFile.Length - 4] == 'p' @@ -21,9 +22,9 @@ private bool ChangeFileNameToTxt(ref char[] newFile) && newFile[newFile.Length - 7] == '.') { Array.Resize(ref newFile, newFile.Length - 3); - newFile[newFile.Length - 1] = 't'; + newFile[newFile.Length - 1] = 'e'; newFile[newFile.Length - 2] = 'x'; - newFile[newFile.Length - 3] = 't'; + newFile[newFile.Length - 3] = 'e'; return true; } else @@ -62,6 +63,16 @@ private bool ChangeFileNameToZipped(ref char[] newFile) } } + private void addAlphabetToBor(Bor bor) + { + var letter = new char[1]; + for (int i = 0; i < 256; ++i) + { + letter[0] = (char)i; + bor.Add(bor, letter, 0, 0); + } + } + private bool CodeFile(string fileName, ref double compressionRatio) { char[] newFileArray = new char[fileName.Length]; @@ -80,103 +91,41 @@ private bool CodeFile(string fileName, ref double compressionRatio) } File.WriteAllText(newFile.ToString(), string.Empty); - // Запись алфавита в бор + var bor = new Bor(); + addAlphabetToBor(bor); + byte[] bufferIn = File.ReadAllBytes(fileName); int j = 0; char[] textFromFile = new char[bufferIn.Length]; - char[] firstAddedAlphabet = new char[bufferIn.Length]; - var fakeBor = new Bor(); - var bor = new Bor(); - int pointer = 0; - for (byte i = 0; i < bufferIn.Length; ++i) + for (int i = 0; i < bufferIn.Length; ++i) { textFromFile[j] = Convert.ToChar(bufferIn[i]); - var (isFirstAdded, _) = bor.Add(bor, textFromFile, j, j); - var (_, _) = fakeBor.Add(bor, textFromFile, j, j); - if (isFirstAdded) - { - firstAddedAlphabet[pointer] = textFromFile[j]; - ++pointer; - } ++j; } - // Проход LZW алгоритма по строке - int walker = 0; - for (int i = 0; i < textFromFile.Length; i++) - { - if (!bor.Contains(textFromFile, walker, i)) - { - var (_, _) = fakeBor.Add(bor, textFromFile, walker, i); - walker = i; - } - } - - int maxFlow = fakeBor.HowManyStringsInBor(); - fakeBor = null; - - // Добавление размера алфавита + символы + ' ' - Array.Resize(ref firstAddedAlphabet, pointer); - char[] alphabet = pointer.ToString().ToCharArray(); - int lastAlphabetSize = alphabet.Length; - char[] maxFlowArray = maxFlow.ToString().ToCharArray(); - Array.Resize(ref alphabet, pointer + alphabet.Length + 2 + maxFlowArray.Length); - alphabet[lastAlphabetSize] = ' '; - int p = 0; - int l = lastAlphabetSize + 1; - while (p < maxFlowArray.Length) - { - alphabet[l] = maxFlowArray[p]; - ++l; - ++p; - } - alphabet[l] = ' '; - ++l; - for (int k = 0; k < firstAddedAlphabet.Length; ++k) - { - alphabet[l] = firstAddedAlphabet[k]; - ++l; - } - - // Запись алфавита - var filestream = new FileStream(newFile, FileMode.OpenOrCreate); - StreamWriter filestreamwriter = new StreamWriter(filestream); - filestreamwriter.Write(alphabet, 0, alphabet.Length); - filestreamwriter.Close(); - filestream.Close(); - // Добавление потоков в файл - walker = 0; + int walker = 0; + int sizeText = textFromFile.Length; for (int i = 0; i < textFromFile.Length; i++) { if (!bor.Contains(textFromFile, walker, i)) { var (_, flow) = bor.Add(bor, textFromFile, walker, i); walker = i; - var bufferOut = new byte[maxFlow]; byte[] bytes = BitConverter.GetBytes(flow); - for (int t = 0; t < bytes.Length; ++t) - { - bufferOut[t] = bytes[t]; - } - var fstreamNew = new FileStream(newFile.ToString(), FileMode.Append); - fstreamNew.WriteAsync(bufferOut, 0, bufferOut.Length); + var fstreamNew = new FileStream(newFile, FileMode.Append); + fstreamNew.WriteAsync(bytes, 0, bytes.Length); fstreamNew.Close(); } } // Добавление последнего потока в файл var flowLast = bor.ReturnFlowByCharArray(textFromFile, bufferIn.Length - 1, bufferIn.Length - 1); - var bufferOutLast = new byte[maxFlow]; byte[] bytesLast = BitConverter.GetBytes(flowLast); - for (int t = 0; t < bytesLast.Length; ++t) - { - bufferOutLast[t] = bytesLast[t]; - } var LastFstreamNew = new FileStream(newFile.ToString(), FileMode.Append); - LastFstreamNew.WriteAsync(bufferOutLast, 0, bufferOutLast.Length); + LastFstreamNew.WriteAsync(bytesLast, 0, bytesLast.Length); LastFstreamNew.Close(); - file = new System.IO.FileInfo(newFile.ToString()); + file = new FileInfo(newFile.ToString()); double newSizeForCompressionRatio = file.Length; compressionRatio = newSizeForCompressionRatio / sizeForCompressionRatio; return true; @@ -185,9 +134,6 @@ private bool CodeFile(string fileName, ref double compressionRatio) private bool DecodeFile(string fileName) { byte[] bufferIn = File.ReadAllBytes(fileName); - char[] stringWithCodes = Encoding.UTF8.GetString(bufferIn).ToCharArray(); - int k = 1; - int sizeAlphabet = 0; int i = 0; char[] newFileArray = new char[fileName.Length]; Array.Copy(fileName.ToCharArray(), newFileArray, fileName.Length); @@ -204,69 +150,69 @@ private bool DecodeFile(string fileName) File.WriteAllText(newFile, string.Empty); - while (stringWithCodes[i] != 32) - { - sizeAlphabet = sizeAlphabet * k + stringWithCodes[i] - 48; - k = 10; - ++i; - } - ++i; - int sizeSymbols = 0; - k = 1; - while (stringWithCodes[i] != 32) - { - sizeSymbols = sizeSymbols * k + stringWithCodes[i] - 48; - k = 10; - ++i; - } - ++i; - var dictionaryForDecode = new Dictionary(); - int sizeFromToInBufferIn = i + sizeAlphabet; - int index = 0; - for(; i < sizeFromToInBufferIn; ++i) + var dictionaryForDecode = new Dictionary(); + + var letter = new char[1]; + for (int j = 0; j < 256; ++j) { - dictionaryForDecode.Add(index, ((char)bufferIn[i]).ToString()); - index++; + var stringLetter = new char[1]; + stringLetter[0] = (char)j; + dictionaryForDecode.Add(j, stringLetter); } + int index = 256; int input = 0; - StringBuilder? previousString = null; + char[] previousString = null; bool isFirst = true; while (i < bufferIn.Length) { - var symbolFromArray = new byte[sizeSymbols]; + var symbolFromArray = new byte[4]; int pointerForSymbolsFromOneArray = 0; - int size = i + sizeSymbols; - for( ; i < size; ++i) + int size = i + 4; + for (; i < size; ++i) { symbolFromArray[pointerForSymbolsFromOneArray] = bufferIn[i]; ++pointerForSymbolsFromOneArray; } + input = BitConverter.ToInt32(symbolFromArray, 0); + if (!isFirst) { if (!dictionaryForDecode.ContainsKey(input)) { - previousString.Append(previousString[0]); - dictionaryForDecode.Add(index, previousString.ToString()); + Array.Resize(ref previousString, previousString.Length + 1); + previousString[previousString.Length - 1] = previousString[0]; + dictionaryForDecode.Add(index, previousString); } var stringByIndex = dictionaryForDecode[input]; if (index != input) { - previousString.Append(stringByIndex[0]); - dictionaryForDecode.Add(index, previousString.ToString()); + Array.Resize(ref previousString, previousString.Length + 1); + previousString[previousString.Length - 1] = stringByIndex[0]; + dictionaryForDecode.Add(index, previousString); + } + FileStream file = File.Open(newFile, FileMode.Append); + foreach (var symbol in stringByIndex) + { + file.WriteByte((byte)symbol); } - File.AppendAllText(newFile, stringByIndex); - previousString = new StringBuilder(stringByIndex); + file.Close(); + previousString = stringByIndex; ++index; } else { var stringByIndex = dictionaryForDecode[input]; - previousString = new StringBuilder(stringByIndex); + previousString = stringByIndex; isFirst = false; - File.AppendAllText(newFile, stringByIndex); + FileStream file = File.Open(newFile, FileMode.Append); + foreach (var symbol in stringByIndex) + { + file.WriteByte((byte)symbol); + } + file.Close(); } } return true; diff --git a/LZW/LZW/Program.cs b/LZW/LZW/Program.cs index a0d1dcf..efc36b5 100644 --- a/LZW/LZW/Program.cs +++ b/LZW/LZW/Program.cs @@ -7,6 +7,7 @@ class Program public static void Main(string[] args) { var lzw = new LZW(); + char le = '©'; var (isCorrect, compressionRatio) = lzw.LzwAlgorithm(args[0], args[1]); if (!isCorrect) { From d724f5d057d90e7f578605be7bc3d3f217abcd61 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 24 Mar 2023 13:32:06 +0300 Subject: [PATCH 04/12] =?UTF-8?q?=D1=80=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LZW/LZW/LZW.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/LZW/LZW/LZW.cs b/LZW/LZW/LZW.cs index 60c3e74..fdd6824 100644 --- a/LZW/LZW/LZW.cs +++ b/LZW/LZW/LZW.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections; -using System.IO; -using System.Text; - -namespace LZW; +namespace LZW; public class LZW { @@ -152,7 +147,6 @@ private bool DecodeFile(string fileName) var dictionaryForDecode = new Dictionary(); - var letter = new char[1]; for (int j = 0; j < 256; ++j) { var stringLetter = new char[1]; @@ -218,6 +212,7 @@ private bool DecodeFile(string fileName) return true; } + // Encodes or decodes a file using the lzw algorithm public (bool, double) LzwAlgorithm(string fileName, string parametr) { if (parametr.Length == 2 && parametr[0] == '-' && parametr[1] == 'c') From fe5311c13d567e3c4326b6007c66c353ca04dc25 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 24 Mar 2023 18:53:40 +0300 Subject: [PATCH 05/12] =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20lzw?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LZW/LZW/LZW.cs | 44 +++++++++-- LZW/TestsForLZW/LZWTests.cs | 79 +++++++++++++++++++ .../Debug/net7.0/TestsForLZW/emptyFile.txt | 0 .../TestsForLZW/testAnElementaryExample.txt | 1 + 4 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 LZW/TestsForLZW/LZWTests.cs create mode 100644 LZW/TestsForLZW/bin/Debug/net7.0/TestsForLZW/emptyFile.txt create mode 100644 LZW/TestsForLZW/bin/Debug/net7.0/TestsForLZW/testAnElementaryExample.txt diff --git a/LZW/LZW/LZW.cs b/LZW/LZW/LZW.cs index fdd6824..98b6629 100644 --- a/LZW/LZW/LZW.cs +++ b/LZW/LZW/LZW.cs @@ -1,4 +1,6 @@ -namespace LZW; +using System.Diagnostics.Tracing; + +namespace LZW; public class LZW { @@ -70,10 +72,19 @@ private void addAlphabetToBor(Bor bor) private bool CodeFile(string fileName, ref double compressionRatio) { - char[] newFileArray = new char[fileName.Length]; - Array.Copy(fileName.ToCharArray(), newFileArray, fileName.Length); - FileInfo file = new System.IO.FileInfo(fileName); - double sizeForCompressionRatio = file.Length; + char[] newFileArray = null; + double sizeForCompressionRatio = 0; + try + { + newFileArray = new char[fileName.Length]; + Array.Copy(fileName.ToCharArray(), newFileArray, fileName.Length); + FileInfo fileFromMain = new FileInfo(fileName); + sizeForCompressionRatio = fileFromMain.Length; + } + catch (FileNotFoundException) + { + return false; + } bool isCorrect = ChangeFileNameToZipped(ref newFileArray); if (!isCorrect) { @@ -84,12 +95,18 @@ private bool CodeFile(string fileName, ref double compressionRatio) { return false; } + File.WriteAllText(newFile.ToString(), string.Empty); var bor = new Bor(); addAlphabetToBor(bor); byte[] bufferIn = File.ReadAllBytes(fileName); + if (bufferIn.Length == 0) + { + compressionRatio = 1; + return true; + } int j = 0; char[] textFromFile = new char[bufferIn.Length]; for (int i = 0; i < bufferIn.Length; ++i) @@ -120,7 +137,7 @@ private bool CodeFile(string fileName, ref double compressionRatio) var LastFstreamNew = new FileStream(newFile.ToString(), FileMode.Append); LastFstreamNew.WriteAsync(bytesLast, 0, bytesLast.Length); LastFstreamNew.Close(); - file = new FileInfo(newFile.ToString()); + var file = new FileInfo(newFile.ToString()); double newSizeForCompressionRatio = file.Length; compressionRatio = newSizeForCompressionRatio / sizeForCompressionRatio; return true; @@ -128,7 +145,15 @@ private bool CodeFile(string fileName, ref double compressionRatio) private bool DecodeFile(string fileName) { - byte[] bufferIn = File.ReadAllBytes(fileName); + byte[] bufferIn = null; + try + { + bufferIn = File.ReadAllBytes(fileName); + } + catch (FileNotFoundException) + { + return false; + } int i = 0; char[] newFileArray = new char[fileName.Length]; Array.Copy(fileName.ToCharArray(), newFileArray, fileName.Length); @@ -145,6 +170,11 @@ private bool DecodeFile(string fileName) File.WriteAllText(newFile, string.Empty); + if (fileName.Length == 0) + { + return true; + } + var dictionaryForDecode = new Dictionary(); for (int j = 0; j < 256; ++j) diff --git a/LZW/TestsForLZW/LZWTests.cs b/LZW/TestsForLZW/LZWTests.cs new file mode 100644 index 0000000..bcfa98f --- /dev/null +++ b/LZW/TestsForLZW/LZWTests.cs @@ -0,0 +1,79 @@ +namespace TestsForLZW; + +using LZW; +using System.Reflection; + +public class Tests +{ + LZW lzw; + [SetUp] + public void Setup() + { + lzw = new LZW(); + } + + [TestCaseSource(nameof(LZW))] + public void TheLZWShouldWorkCorrectlyToReturnTheCorrectValueOnASimpleExample(LZW lzw) + { + Setup(); + var (isCorrect, _) = lzw.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.txt"), "-c"); + if (!isCorrect ) + { + Assert.Fail(); + } + (isCorrect, var _) = lzw.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.zipped"), "-u"); + if (!isCorrect) + { + Assert.Fail(); + } + string correctText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.txt")); + string fromLZWText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.exe")); + Assert.True(correctText == fromLZWText); + } + + [TestCaseSource(nameof(LZW))] + public void LZWCodeingShouldReturnFalseWhenReceivingAFileWithAnIncorrectName(LZW lzw) + { + var (isCorrect, _) = lzw.LzwAlgorithm("ds", "-c"); + Assert.False(isCorrect); + } + + [TestCaseSource(nameof(LZW))] + public void LZWDecodeingShouldReturnFalseWhenReceivingAFileWithAnIncorrectName(LZW lzw) + { + var (isCorrect, _) = lzw.LzwAlgorithm("ds", "-u"); + Assert.False(isCorrect); + } + + [TestCaseSource(nameof(LZW))] + public void LZWShouldReturnFalseWhenReceivingAFileWithAnIncorrectParametr(LZW lzw) + { + var (isCorrect, _) = lzw.LzwAlgorithm("ds", "-e"); + Assert.False(isCorrect); + } + + [TestCaseSource(nameof(LZW))] + public void TheLZWShouldReturnAnEmptyFileEmpty(LZW lzw) + { + Setup(); + var (isCorrect, _) = lzw.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.txt"), "-c"); + if (!isCorrect) + { + Assert.Fail(); + } + (isCorrect, var _) = lzw.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.zipped"), "-u"); + if (!isCorrect) + { + Assert.Fail(); + } + string correctText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.txt")); + string fromLZWText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.exe")); + Assert.True(correctText == fromLZWText); + } + + private static IEnumerable LZW + => new TestCaseData[] + { + new TestCaseData(new LZW()), + }; +} \ No newline at end of file diff --git a/LZW/TestsForLZW/bin/Debug/net7.0/TestsForLZW/emptyFile.txt b/LZW/TestsForLZW/bin/Debug/net7.0/TestsForLZW/emptyFile.txt new file mode 100644 index 0000000..e69de29 diff --git a/LZW/TestsForLZW/bin/Debug/net7.0/TestsForLZW/testAnElementaryExample.txt b/LZW/TestsForLZW/bin/Debug/net7.0/TestsForLZW/testAnElementaryExample.txt new file mode 100644 index 0000000..1acd2c7 --- /dev/null +++ b/LZW/TestsForLZW/bin/Debug/net7.0/TestsForLZW/testAnElementaryExample.txt @@ -0,0 +1 @@ +abacabadabae \ No newline at end of file From 9f73e583358a22b33eea97771a5140dff5ab7959 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 24 Mar 2023 20:23:29 +0300 Subject: [PATCH 06/12] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20+=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20?= =?UTF-8?q?=D0=BA=20=D0=B1=D0=BE=D1=80=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LZW/LZW.sln | 8 ++++- LZW/LZW/Bor.cs | 8 ++++- LZW/LZW/Program.cs | 1 - LZW/TestsForBor/TestForBor.cs | 58 +++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 LZW/TestsForBor/TestForBor.cs diff --git a/LZW/LZW.sln b/LZW/LZW.sln index 5f47f6c..283a85f 100644 --- a/LZW/LZW.sln +++ b/LZW/LZW.sln @@ -5,7 +5,9 @@ VisualStudioVersion = 17.4.33403.182 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LZW", "LZW\LZW.csproj", "{B99BFF18-B071-406A-989E-994845F53D3B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsForLZW", "TestsForLZW\TestsForLZW.csproj", "{C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestsForLZW", "TestsForLZW\TestsForLZW.csproj", "{C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsForBor", "TestsForBor\TestsForBor.csproj", "{29F62813-6598-47FA-BDA4-00FEF655C851}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +23,10 @@ Global {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Debug|Any CPU.Build.0 = Debug|Any CPU {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Release|Any CPU.ActiveCfg = Release|Any CPU {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Release|Any CPU.Build.0 = Release|Any CPU + {29F62813-6598-47FA-BDA4-00FEF655C851}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {29F62813-6598-47FA-BDA4-00FEF655C851}.Debug|Any CPU.Build.0 = Debug|Any CPU + {29F62813-6598-47FA-BDA4-00FEF655C851}.Release|Any CPU.ActiveCfg = Release|Any CPU + {29F62813-6598-47FA-BDA4-00FEF655C851}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/LZW/LZW/Bor.cs b/LZW/LZW/Bor.cs index 307bade..b3cb4f7 100644 --- a/LZW/LZW/Bor.cs +++ b/LZW/LZW/Bor.cs @@ -1,4 +1,4 @@ -namespace LZW; +namespace Bor; // A container for storing strings, in the form of a suspended tree public class Bor @@ -43,8 +43,13 @@ public class Bor return walker.IsTerminal == false ? (walker.IsTerminal = true && true, toFlow) : (false, toFlow); } + // Returns flow by letter public int ReturnFlowByCharArray(char[] buffer, int to, int from) { + if (buffer.Length == 0) + { + return -1; + } var walker = root; int i = 0; int pointer = from; @@ -61,6 +66,7 @@ public int ReturnFlowByCharArray(char[] buffer, int to, int from) return walker.Flow; } + // Returns how many strings in bor public int HowManyStringsInBor() { if (root == null) diff --git a/LZW/LZW/Program.cs b/LZW/LZW/Program.cs index efc36b5..a0d1dcf 100644 --- a/LZW/LZW/Program.cs +++ b/LZW/LZW/Program.cs @@ -7,7 +7,6 @@ class Program public static void Main(string[] args) { var lzw = new LZW(); - char le = '©'; var (isCorrect, compressionRatio) = lzw.LzwAlgorithm(args[0], args[1]); if (!isCorrect) { diff --git a/LZW/TestsForBor/TestForBor.cs b/LZW/TestsForBor/TestForBor.cs new file mode 100644 index 0000000..c765038 --- /dev/null +++ b/LZW/TestsForBor/TestForBor.cs @@ -0,0 +1,58 @@ +namespace TestsForBor; + +using Bor; +public class TestsForBor +{ + Bor bor; + [SetUp] + public void Setup() + { + bor = new Bor(); + } + + [TestCaseSource(nameof(BorForTests))] + public void TheAddedElementShouldbeFoundInBor(Bor bor) + { + Setup(); + bor.Add(bor, "end".ToCharArray(), 0, 2); + Assert.True(bor.Contains("end".ToCharArray(), 0, 2), "Problems with the addition test!\n"); + } + + [TestCaseSource(nameof(BorForTests))] + public void WhenAddingTwoLinesToBorTheBorShouldIncludeTwoLines(Bor bor) + { + Setup(); + bor.Add(bor, "endProgram".ToCharArray(), 0, 9); + bor.Add(bor, "endFunction".ToCharArray(), 0, 10); + Assert.True(bor.HowManyStringsInBor() == 2, "Problems with the prefix test!"); + } + + [TestCaseSource(nameof(BorForTests))] + public void WhenAddingTheSymbolFlowInTheBorShouldBeCorrect(Bor bor) + { + Setup(); + bor.Add(bor, "a".ToCharArray(), 0, 0); + bor.Add(bor, "b".ToCharArray(), 0, 0); + Assert.True(bor.ReturnFlowByCharArray("b".ToCharArray(), 0, 0) == 1, "Problems with the prefix test!"); + } + + [TestCaseSource(nameof(BorForTests))] + public void TheInitializedBorShouldBeEmpty(Bor bor) + { + Setup(); + Assert.False(bor.Contains("end".ToCharArray(), 0, 2), "Problems with the prefix test!"); + } + + [TestCaseSource(nameof(BorForTests))] + public void ThereShouldBeNoThreadsInTheCreatedBor(Bor bor) + { + Setup(); + Assert.True(bor.ReturnFlowByCharArray("".ToCharArray(), 0, 0) == -1, "Problems with the prefix test!"); + } + + private static IEnumerable BorForTests + => new TestCaseData[] + { + new TestCaseData(new Bor()), + }; +} \ No newline at end of file From 1724fd1ffc5f156da8eeb979fe26c321cc2efbbf Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 25 Mar 2023 20:15:43 +0300 Subject: [PATCH 07/12] =?UTF-8?q?=D1=80=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LZW/LZW/LZW.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LZW/LZW/LZW.cs b/LZW/LZW/LZW.cs index 98b6629..766fc0c 100644 --- a/LZW/LZW/LZW.cs +++ b/LZW/LZW/LZW.cs @@ -1,6 +1,6 @@ -using System.Diagnostics.Tracing; +namespace LZW; -namespace LZW; +using Bor; public class LZW { From 8d51730f6ca06665fdcafcdc365156fea9817bcb Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 31 Mar 2023 01:10:42 +0300 Subject: [PATCH 08/12] +CI --- LZW/LZW.sln | 16 +++++++++---- .../LZWTests.cs => TestLZW/TestLZW.cs} | 2 +- LZW/TestLZW/TestLZW.csproj | 23 +++++++++++++++++++ LZW/TestLZW/Usings.cs | 1 + .../Debug/net7.0/TestsForLZW/emptyFile.txt | 0 .../TestsForLZW/testAnElementaryExample.txt | 0 .../TestForBor.cs => TestsBor/TestsBor.cs} | 0 LZW/TestsBor/TestsBor.csproj | 23 +++++++++++++++++++ LZW/TestsBor/Usings.cs | 1 + 9 files changed, 60 insertions(+), 6 deletions(-) rename LZW/{TestsForLZW/LZWTests.cs => TestLZW/TestLZW.cs} (99%) create mode 100644 LZW/TestLZW/TestLZW.csproj create mode 100644 LZW/TestLZW/Usings.cs rename LZW/{TestsForLZW => TestLZW}/bin/Debug/net7.0/TestsForLZW/emptyFile.txt (100%) rename LZW/{TestsForLZW => TestLZW}/bin/Debug/net7.0/TestsForLZW/testAnElementaryExample.txt (100%) rename LZW/{TestsForBor/TestForBor.cs => TestsBor/TestsBor.cs} (100%) create mode 100644 LZW/TestsBor/TestsBor.csproj create mode 100644 LZW/TestsBor/Usings.cs diff --git a/LZW/LZW.sln b/LZW/LZW.sln index 283a85f..8d61c97 100644 --- a/LZW/LZW.sln +++ b/LZW/LZW.sln @@ -7,7 +7,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LZW", "LZW\LZW.csproj", "{B EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestsForLZW", "TestsForLZW\TestsForLZW.csproj", "{C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsForBor", "TestsForBor\TestsForBor.csproj", "{29F62813-6598-47FA-BDA4-00FEF655C851}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsBor", "TestsBor\TestsBor.csproj", "{019B956A-4284-4708-9B93-8D6FC218A62E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestLZW", "TestLZW\TestLZW.csproj", "{C3A8A289-5E8E-4D79-8263-3E4726F4A4CD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -23,10 +25,14 @@ Global {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Debug|Any CPU.Build.0 = Debug|Any CPU {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Release|Any CPU.ActiveCfg = Release|Any CPU {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Release|Any CPU.Build.0 = Release|Any CPU - {29F62813-6598-47FA-BDA4-00FEF655C851}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {29F62813-6598-47FA-BDA4-00FEF655C851}.Debug|Any CPU.Build.0 = Debug|Any CPU - {29F62813-6598-47FA-BDA4-00FEF655C851}.Release|Any CPU.ActiveCfg = Release|Any CPU - {29F62813-6598-47FA-BDA4-00FEF655C851}.Release|Any CPU.Build.0 = Release|Any CPU + {019B956A-4284-4708-9B93-8D6FC218A62E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {019B956A-4284-4708-9B93-8D6FC218A62E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {019B956A-4284-4708-9B93-8D6FC218A62E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {019B956A-4284-4708-9B93-8D6FC218A62E}.Release|Any CPU.Build.0 = Release|Any CPU + {C3A8A289-5E8E-4D79-8263-3E4726F4A4CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3A8A289-5E8E-4D79-8263-3E4726F4A4CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3A8A289-5E8E-4D79-8263-3E4726F4A4CD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3A8A289-5E8E-4D79-8263-3E4726F4A4CD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/LZW/TestsForLZW/LZWTests.cs b/LZW/TestLZW/TestLZW.cs similarity index 99% rename from LZW/TestsForLZW/LZWTests.cs rename to LZW/TestLZW/TestLZW.cs index bcfa98f..1907e7d 100644 --- a/LZW/TestsForLZW/LZWTests.cs +++ b/LZW/TestLZW/TestLZW.cs @@ -1,4 +1,4 @@ -namespace TestsForLZW; +namespace TestLZW; using LZW; using System.Reflection; diff --git a/LZW/TestLZW/TestLZW.csproj b/LZW/TestLZW/TestLZW.csproj new file mode 100644 index 0000000..cfd3a15 --- /dev/null +++ b/LZW/TestLZW/TestLZW.csproj @@ -0,0 +1,23 @@ + + + + net7.0 + enable + enable + + false + + + + + + + + + + + + + + + diff --git a/LZW/TestLZW/Usings.cs b/LZW/TestLZW/Usings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/LZW/TestLZW/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/LZW/TestsForLZW/bin/Debug/net7.0/TestsForLZW/emptyFile.txt b/LZW/TestLZW/bin/Debug/net7.0/TestsForLZW/emptyFile.txt similarity index 100% rename from LZW/TestsForLZW/bin/Debug/net7.0/TestsForLZW/emptyFile.txt rename to LZW/TestLZW/bin/Debug/net7.0/TestsForLZW/emptyFile.txt diff --git a/LZW/TestsForLZW/bin/Debug/net7.0/TestsForLZW/testAnElementaryExample.txt b/LZW/TestLZW/bin/Debug/net7.0/TestsForLZW/testAnElementaryExample.txt similarity index 100% rename from LZW/TestsForLZW/bin/Debug/net7.0/TestsForLZW/testAnElementaryExample.txt rename to LZW/TestLZW/bin/Debug/net7.0/TestsForLZW/testAnElementaryExample.txt diff --git a/LZW/TestsForBor/TestForBor.cs b/LZW/TestsBor/TestsBor.cs similarity index 100% rename from LZW/TestsForBor/TestForBor.cs rename to LZW/TestsBor/TestsBor.cs diff --git a/LZW/TestsBor/TestsBor.csproj b/LZW/TestsBor/TestsBor.csproj new file mode 100644 index 0000000..cfd3a15 --- /dev/null +++ b/LZW/TestsBor/TestsBor.csproj @@ -0,0 +1,23 @@ + + + + net7.0 + enable + enable + + false + + + + + + + + + + + + + + + diff --git a/LZW/TestsBor/Usings.cs b/LZW/TestsBor/Usings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/LZW/TestsBor/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file From c21a82e935d6f1e46cd15bf1605ad05768d4bd3d Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 31 Mar 2023 01:17:22 +0300 Subject: [PATCH 09/12] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20sln?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LZW/LZW.sln | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/LZW/LZW.sln b/LZW/LZW.sln index 8d61c97..bee34d3 100644 --- a/LZW/LZW.sln +++ b/LZW/LZW.sln @@ -5,11 +5,9 @@ VisualStudioVersion = 17.4.33403.182 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LZW", "LZW\LZW.csproj", "{B99BFF18-B071-406A-989E-994845F53D3B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestsForLZW", "TestsForLZW\TestsForLZW.csproj", "{C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestsBor", "TestsBor\TestsBor.csproj", "{019B956A-4284-4708-9B93-8D6FC218A62E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsBor", "TestsBor\TestsBor.csproj", "{019B956A-4284-4708-9B93-8D6FC218A62E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestLZW", "TestLZW\TestLZW.csproj", "{C3A8A289-5E8E-4D79-8263-3E4726F4A4CD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestLZW", "TestLZW\TestLZW.csproj", "{C3A8A289-5E8E-4D79-8263-3E4726F4A4CD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,10 +19,6 @@ Global {B99BFF18-B071-406A-989E-994845F53D3B}.Debug|Any CPU.Build.0 = Debug|Any CPU {B99BFF18-B071-406A-989E-994845F53D3B}.Release|Any CPU.ActiveCfg = Release|Any CPU {B99BFF18-B071-406A-989E-994845F53D3B}.Release|Any CPU.Build.0 = Release|Any CPU - {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C67B3F54-F6D7-41A6-A1C8-BAF1DE66871B}.Release|Any CPU.Build.0 = Release|Any CPU {019B956A-4284-4708-9B93-8D6FC218A62E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {019B956A-4284-4708-9B93-8D6FC218A62E}.Debug|Any CPU.Build.0 = Debug|Any CPU {019B956A-4284-4708-9B93-8D6FC218A62E}.Release|Any CPU.ActiveCfg = Release|Any CPU From facd872b0ab93a8b6e2103a50ba5164d01f71067 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 25 May 2023 19:31:27 +0300 Subject: [PATCH 10/12] =?UTF-8?q?=D0=A0=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LZW/LZW/Bor.cs | 50 ++++++-- LZW/LZW/LZW.cs | 120 ++++++------------ LZW/LZW/Program.cs | 3 +- LZW/TestLZW/TestLZW.cs | 70 ++++------ .../net7.0/TestsForLZW/correctEmptyFile.txt | 0 .../correctTestAnElementaryExample.txt | 1 + LZW/TestsBor/TestsBor.cs | 40 +++--- 7 files changed, 125 insertions(+), 159 deletions(-) create mode 100644 LZW/TestLZW/bin/Debug/net7.0/TestsForLZW/correctEmptyFile.txt create mode 100644 LZW/TestLZW/bin/Debug/net7.0/TestsForLZW/correctTestAnElementaryExample.txt diff --git a/LZW/LZW/Bor.cs b/LZW/LZW/Bor.cs index b3cb4f7..66f2617 100644 --- a/LZW/LZW/Bor.cs +++ b/LZW/LZW/Bor.cs @@ -1,14 +1,23 @@ namespace Bor; -// A container for storing strings, in the form of a suspended tree +/// +/// String Parsing Tree +/// public class Bor { - private BorElement root = new BorElement(); + private BorElement root = new(); - // Adding an element - public (bool, int) Add(Bor bor, char[] buffer, int from, int to) + /// + /// Adding an element to a Trie + /// + public (bool, int) Add(char[] buffer, int from = 0, int to = 0) { - if (root == null || buffer == null) + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + + if (root == null) { throw new InvalidOperationException(); } @@ -16,7 +25,7 @@ public class Bor int i = 0; int pointer = from; int toFlow = -1; - bool isStringInBor = bor.Contains(buffer, from, to); + bool isStringInBor = Contains(buffer, from, to); while (i < to - from + 1) { int number = (int)buffer[pointer]; @@ -34,17 +43,28 @@ public class Bor pointer++; i++; } - if (walker.IsTerminal == false) + if (!walker.IsTerminal) { walker.Flow = root.HowManyStringInDictionary; root.HowManyStringInDictionary++; } - return walker.IsTerminal == false ? (walker.IsTerminal = true && true, toFlow) : (false, toFlow); + if (!walker.IsTerminal) + { + walker.IsTerminal = true; + return (true, toFlow); + } + else + { + return (true, toFlow); + } + } - // Returns flow by letter - public int ReturnFlowByCharArray(char[] buffer, int to, int from) + /// + /// Returns a stream by letter + /// + public int ReturnFlowByCharArray(char[] buffer, int to = 0, int from = 0) { if (buffer.Length == 0) { @@ -66,7 +86,9 @@ public int ReturnFlowByCharArray(char[] buffer, int to, int from) return walker.Flow; } - // Returns how many strings in bor + /// + /// Returns how many strings in a Trie + /// public int HowManyStringsInBor() { if (root == null) @@ -76,8 +98,10 @@ public int HowManyStringsInBor() return root.HowManyStringInDictionary; } - // Checks for the presence of a string - public bool Contains(char[] buffer, int from, int to) + /// + /// Checks whether the string in the Trie contains + /// + public bool Contains(char[] buffer, int from = 0 , int to = 0) { if (root == null) { diff --git a/LZW/LZW/LZW.cs b/LZW/LZW/LZW.cs index 766fc0c..10edf4a 100644 --- a/LZW/LZW/LZW.cs +++ b/LZW/LZW/LZW.cs @@ -2,104 +2,69 @@ using Bor; -public class LZW +/// +/// A class for compressing and decompressing data using the LZW algorithm +/// +public static class LZWAlgorithm { - private bool ChangeFileNameToTxt(ref char[] newFile) + private static void ChangeFileNameToTheOriginalName(ref char[] newFile) { if (newFile.Length < 8) { - return false; - } - if (newFile[newFile.Length - 1] == 'd' - && newFile[newFile.Length - 2] == 'e' - && newFile[newFile.Length - 3] == 'p' - && newFile[newFile.Length - 4] == 'p' - && newFile[newFile.Length - 5] == 'i' - && newFile[newFile.Length - 6] == 'z' - && newFile[newFile.Length - 7] == '.') - { - Array.Resize(ref newFile, newFile.Length - 3); - newFile[newFile.Length - 1] = 'e'; - newFile[newFile.Length - 2] = 'x'; - newFile[newFile.Length - 3] = 'e'; - return true; - } - else - { - return false; + throw new ArgumentException(); } + Array.Resize(ref newFile, newFile.Length - 7); } - private bool ChangeFileNameToZipped(ref char[] newFile) + private static void ChangeFileNameToZipped(ref char[] newFile) { - if (newFile.Length < 5) - { - return false; - } - if (newFile[newFile.Length - 1] == 't' - && newFile[newFile.Length - 2] == 'x' - && newFile[newFile.Length - 3] == 't' - && newFile[newFile.Length - 4] == '.' - || newFile[newFile.Length - 1] == 'e' - && newFile[newFile.Length - 2] == 'x' - && newFile[newFile.Length - 3] == 'e' - && newFile[newFile.Length - 4] == '.') - { - Array.Resize(ref newFile, newFile.Length + 3); - newFile[newFile.Length - 1] = 'd'; - newFile[newFile.Length - 2] = 'e'; - newFile[newFile.Length - 3] = 'p'; - newFile[newFile.Length - 4] = 'p'; - newFile[newFile.Length - 5] = 'i'; - newFile[newFile.Length - 6] = 'z'; - return true; - } - else - { - return false; - } + int sizeNewFile = newFile.Length; + Array.Resize(ref newFile, sizeNewFile + 7); + newFile[sizeNewFile] = '.'; + newFile[sizeNewFile + 1] = 'z'; + newFile[sizeNewFile + 2] = 'i'; + newFile[sizeNewFile + 3] = 'p'; + newFile[sizeNewFile + 4] = 'p'; + newFile[sizeNewFile + 5] = 'e'; + newFile[sizeNewFile + 6] = 'd'; } - private void addAlphabetToBor(Bor bor) + private static void AddAlphabetToBor(Bor bor) { var letter = new char[1]; for (int i = 0; i < 256; ++i) { letter[0] = (char)i; - bor.Add(bor, letter, 0, 0); + bor.Add(letter, 0, 0); } } - private bool CodeFile(string fileName, ref double compressionRatio) + private static bool CodeFile(string fileName, ref double compressionRatio) { - char[] newFileArray = null; + char[]? newFileArray = null; double sizeForCompressionRatio = 0; try { newFileArray = new char[fileName.Length]; Array.Copy(fileName.ToCharArray(), newFileArray, fileName.Length); - FileInfo fileFromMain = new FileInfo(fileName); + FileInfo fileFromMain = new(fileName); sizeForCompressionRatio = fileFromMain.Length; } catch (FileNotFoundException) { return false; } - bool isCorrect = ChangeFileNameToZipped(ref newFileArray); - if (!isCorrect) - { - return false; - } + ChangeFileNameToZipped(ref newFileArray); string? newFile = new string(newFileArray); if (newFile == null) { return false; } - File.WriteAllText(newFile.ToString(), string.Empty); + File.WriteAllText(newFile, string.Empty); var bor = new Bor(); - addAlphabetToBor(bor); + AddAlphabetToBor(bor); byte[] bufferIn = File.ReadAllBytes(fileName); if (bufferIn.Length == 0) @@ -108,7 +73,7 @@ private bool CodeFile(string fileName, ref double compressionRatio) return true; } int j = 0; - char[] textFromFile = new char[bufferIn.Length]; + var textFromFile = new char[bufferIn.Length]; for (int i = 0; i < bufferIn.Length; ++i) { textFromFile[j] = Convert.ToChar(bufferIn[i]); @@ -118,32 +83,30 @@ private bool CodeFile(string fileName, ref double compressionRatio) // Добавление потоков в файл int walker = 0; int sizeText = textFromFile.Length; + var fstreamNew = new FileStream(newFile, FileMode.Append); for (int i = 0; i < textFromFile.Length; i++) { if (!bor.Contains(textFromFile, walker, i)) { - var (_, flow) = bor.Add(bor, textFromFile, walker, i); + var (_, flow) = bor.Add(textFromFile, walker, i); walker = i; byte[] bytes = BitConverter.GetBytes(flow); - var fstreamNew = new FileStream(newFile, FileMode.Append); fstreamNew.WriteAsync(bytes, 0, bytes.Length); - fstreamNew.Close(); } } // Добавление последнего потока в файл var flowLast = bor.ReturnFlowByCharArray(textFromFile, bufferIn.Length - 1, bufferIn.Length - 1); byte[] bytesLast = BitConverter.GetBytes(flowLast); - var LastFstreamNew = new FileStream(newFile.ToString(), FileMode.Append); - LastFstreamNew.WriteAsync(bytesLast, 0, bytesLast.Length); - LastFstreamNew.Close(); + fstreamNew.WriteAsync(bytesLast, 0, bytesLast.Length); + fstreamNew.Close(); var file = new FileInfo(newFile.ToString()); double newSizeForCompressionRatio = file.Length; compressionRatio = newSizeForCompressionRatio / sizeForCompressionRatio; return true; } - private bool DecodeFile(string fileName) + private static bool DecodeFile(string fileName) { byte[] bufferIn = null; try @@ -155,13 +118,9 @@ private bool DecodeFile(string fileName) return false; } int i = 0; - char[] newFileArray = new char[fileName.Length]; + var newFileArray = new char[fileName.Length]; Array.Copy(fileName.ToCharArray(), newFileArray, fileName.Length); - bool isCorrect = ChangeFileNameToTxt(ref newFileArray); - if (!isCorrect) - { - return false; - } + ChangeFileNameToTheOriginalName(ref newFileArray); string? newFile = new string(newFileArray); if (newFile == null) { @@ -190,7 +149,6 @@ private bool DecodeFile(string fileName) bool isFirst = true; while (i < bufferIn.Length) { - var symbolFromArray = new byte[4]; int pointerForSymbolsFromOneArray = 0; int size = i + 4; @@ -242,16 +200,20 @@ private bool DecodeFile(string fileName) return true; } - // Encodes or decodes a file using the lzw algorithm - public (bool, double) LzwAlgorithm(string fileName, string parametr) + /// + /// Function for accepting data + /// + /// Shows decompression or compression + /// Returns whether it was executed correctly and what is the compression percentage + public static (bool, double) LzwAlgorithm(string fileName, string parameter) { - if (parametr.Length == 2 && parametr[0] == '-' && parametr[1] == 'c') + if (parameter.Length == 2 && parameter[0] == '-' && parameter[1] == 'c') { double compressionRatio = 0; var isCorrect = CodeFile(fileName, ref compressionRatio); return (isCorrect, compressionRatio); } - else if (parametr.Length == 2 && parametr[0] == '-' && parametr[1] == 'u') + else if (parameter.Length == 2 && parameter[0] == '-' && parameter[1] == 'u') { return (DecodeFile(fileName), 0); } diff --git a/LZW/LZW/Program.cs b/LZW/LZW/Program.cs index a0d1dcf..7c76a42 100644 --- a/LZW/LZW/Program.cs +++ b/LZW/LZW/Program.cs @@ -6,8 +6,7 @@ class Program { public static void Main(string[] args) { - var lzw = new LZW(); - var (isCorrect, compressionRatio) = lzw.LzwAlgorithm(args[0], args[1]); + var (isCorrect, compressionRatio) = LZWAlgorithm.LzwAlgorithm(args[0], args[1]); if (!isCorrect) { Console.WriteLine("Problems..."); diff --git a/LZW/TestLZW/TestLZW.cs b/LZW/TestLZW/TestLZW.cs index 1907e7d..4b93848 100644 --- a/LZW/TestLZW/TestLZW.cs +++ b/LZW/TestLZW/TestLZW.cs @@ -1,79 +1,63 @@ namespace TestLZW; using LZW; -using System.Reflection; public class Tests { - LZW lzw; - [SetUp] - public void Setup() + [Test] + public void TheLZWShouldWorkCorrectlyToReturnTheCorrectValueOnASimpleExample() { - lzw = new LZW(); - } - - [TestCaseSource(nameof(LZW))] - public void TheLZWShouldWorkCorrectlyToReturnTheCorrectValueOnASimpleExample(LZW lzw) - { - Setup(); - var (isCorrect, _) = lzw.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.txt"), "-c"); + var (isCorrect, _) = LZWAlgorithm.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.txt"), "-c"); if (!isCorrect ) { - Assert.Fail(); + Assert.That(false, Is.EqualTo(!isCorrect)); } - (isCorrect, var _) = lzw.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.zipped"), "-u"); + (isCorrect, var _) = LZWAlgorithm.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.txt.zipped"), "-u"); if (!isCorrect) { - Assert.Fail(); + Assert.That(false, Is.EqualTo(!isCorrect)); } - string correctText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.txt")); - string fromLZWText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.exe")); - Assert.True(correctText == fromLZWText); + string correctText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "correctTestAnElementaryExample.txt")); + string fromLZWText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.txt")); + Assert.That(correctText, Is.EqualTo(fromLZWText)); } - [TestCaseSource(nameof(LZW))] - public void LZWCodeingShouldReturnFalseWhenReceivingAFileWithAnIncorrectName(LZW lzw) + [Test] + public void LZWCodeingShouldReturnFalseWhenReceivingAFileWithAnIncorrectName() { - var (isCorrect, _) = lzw.LzwAlgorithm("ds", "-c"); + var (isCorrect, _) = LZWAlgorithm.LzwAlgorithm("ds", "-c"); Assert.False(isCorrect); } - [TestCaseSource(nameof(LZW))] - public void LZWDecodeingShouldReturnFalseWhenReceivingAFileWithAnIncorrectName(LZW lzw) + [Test] + public void LZWDecodeingShouldReturnFalseWhenReceivingAFileWithAnIncorrectName() { - var (isCorrect, _) = lzw.LzwAlgorithm("ds", "-u"); + var (isCorrect, _) = LZWAlgorithm.LzwAlgorithm("ds", "-u"); Assert.False(isCorrect); } - [TestCaseSource(nameof(LZW))] - public void LZWShouldReturnFalseWhenReceivingAFileWithAnIncorrectParametr(LZW lzw) + [Test] + public void LZWShouldReturnFalseWhenReceivingAFileWithAnIncorrectParametr() { - var (isCorrect, _) = lzw.LzwAlgorithm("ds", "-e"); + var (isCorrect, _) = LZWAlgorithm.LzwAlgorithm("ds", "-e"); Assert.False(isCorrect); } - [TestCaseSource(nameof(LZW))] - public void TheLZWShouldReturnAnEmptyFileEmpty(LZW lzw) + [Test] + public void TheLZWShouldReturnAnEmptyFileEmpty() { - Setup(); - var (isCorrect, _) = lzw.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.txt"), "-c"); + var (isCorrect, _) = LZWAlgorithm.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.txt"), "-c"); if (!isCorrect) { - Assert.Fail(); + Assert.That(false, Is.EqualTo(!isCorrect)); } - (isCorrect, var _) = lzw.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.zipped"), "-u"); + (isCorrect, var _) = LZWAlgorithm.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.txt.zipped"), "-u"); if (!isCorrect) { - Assert.Fail(); + Assert.That(false, Is.EqualTo(!isCorrect)); } - string correctText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.txt")); - string fromLZWText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.exe")); - Assert.True(correctText == fromLZWText); + string fromLZWText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.txt")); + string correctText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "correctEmptyFile.txt")); + Assert.That(correctText, Is.EqualTo(fromLZWText)); } - - private static IEnumerable LZW - => new TestCaseData[] - { - new TestCaseData(new LZW()), - }; } \ No newline at end of file diff --git a/LZW/TestLZW/bin/Debug/net7.0/TestsForLZW/correctEmptyFile.txt b/LZW/TestLZW/bin/Debug/net7.0/TestsForLZW/correctEmptyFile.txt new file mode 100644 index 0000000..e69de29 diff --git a/LZW/TestLZW/bin/Debug/net7.0/TestsForLZW/correctTestAnElementaryExample.txt b/LZW/TestLZW/bin/Debug/net7.0/TestsForLZW/correctTestAnElementaryExample.txt new file mode 100644 index 0000000..1acd2c7 --- /dev/null +++ b/LZW/TestLZW/bin/Debug/net7.0/TestsForLZW/correctTestAnElementaryExample.txt @@ -0,0 +1 @@ +abacabadabae \ No newline at end of file diff --git a/LZW/TestsBor/TestsBor.cs b/LZW/TestsBor/TestsBor.cs index c765038..7198a7b 100644 --- a/LZW/TestsBor/TestsBor.cs +++ b/LZW/TestsBor/TestsBor.cs @@ -1,58 +1,54 @@ namespace TestsForBor; using Bor; + public class TestsForBor { - Bor bor; + private Bor bor; + [SetUp] public void Setup() { bor = new Bor(); } - [TestCaseSource(nameof(BorForTests))] - public void TheAddedElementShouldbeFoundInBor(Bor bor) + [Test] + public void TheAddedElementShouldbeFoundInBor() { Setup(); - bor.Add(bor, "end".ToCharArray(), 0, 2); + bor.Add("end".ToCharArray(), 0, 2); Assert.True(bor.Contains("end".ToCharArray(), 0, 2), "Problems with the addition test!\n"); } - [TestCaseSource(nameof(BorForTests))] - public void WhenAddingTwoLinesToBorTheBorShouldIncludeTwoLines(Bor bor) + [Test] + public void WhenAddingTwoLinesToBorTheBorShouldIncludeTwoLines() { Setup(); - bor.Add(bor, "endProgram".ToCharArray(), 0, 9); - bor.Add(bor, "endFunction".ToCharArray(), 0, 10); + bor.Add("endProgram".ToCharArray(), 0, 9); + bor.Add("endFunction".ToCharArray(), 0, 10); Assert.True(bor.HowManyStringsInBor() == 2, "Problems with the prefix test!"); } - [TestCaseSource(nameof(BorForTests))] - public void WhenAddingTheSymbolFlowInTheBorShouldBeCorrect(Bor bor) + [Test] + public void WhenAddingTheSymbolFlowInTheBorShouldBeCorrect() { Setup(); - bor.Add(bor, "a".ToCharArray(), 0, 0); - bor.Add(bor, "b".ToCharArray(), 0, 0); + bor.Add("a".ToCharArray(), 0, 0); + bor.Add("b".ToCharArray(), 0, 0); Assert.True(bor.ReturnFlowByCharArray("b".ToCharArray(), 0, 0) == 1, "Problems with the prefix test!"); } - [TestCaseSource(nameof(BorForTests))] - public void TheInitializedBorShouldBeEmpty(Bor bor) + [Test] + public void TheInitializedBorShouldBeEmpty() { Setup(); Assert.False(bor.Contains("end".ToCharArray(), 0, 2), "Problems with the prefix test!"); } - [TestCaseSource(nameof(BorForTests))] - public void ThereShouldBeNoThreadsInTheCreatedBor(Bor bor) + [Test] + public void ThereShouldBeNoThreadsInTheCreatedBor() { - Setup(); Assert.True(bor.ReturnFlowByCharArray("".ToCharArray(), 0, 0) == -1, "Problems with the prefix test!"); } - private static IEnumerable BorForTests - => new TestCaseData[] - { - new TestCaseData(new Bor()), - }; } \ No newline at end of file From 32d0afc384ec2bfd7e413f2a480471f7e693082a Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 26 May 2023 15:22:24 +0300 Subject: [PATCH 11/12] =?UTF-8?q?=D0=A0=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LZW/LZW/LZW.cs | 6 ++++-- LZW/TestLZW/TestLZW.cs | 20 ++++---------------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/LZW/LZW/LZW.cs b/LZW/LZW/LZW.cs index 10edf4a..b82b4de 100644 --- a/LZW/LZW/LZW.cs +++ b/LZW/LZW/LZW.cs @@ -108,7 +108,7 @@ private static bool CodeFile(string fileName, ref double compressionRatio) private static bool DecodeFile(string fileName) { - byte[] bufferIn = null; + byte[]? bufferIn = null; try { bufferIn = File.ReadAllBytes(fileName); @@ -145,7 +145,7 @@ private static bool DecodeFile(string fileName) int index = 256; int input = 0; - char[] previousString = null; + char[]? previousString = null; bool isFirst = true; while (i < bufferIn.Length) { @@ -164,6 +164,7 @@ private static bool DecodeFile(string fileName) { if (!dictionaryForDecode.ContainsKey(input)) { + ArgumentNullException.ThrowIfNull(previousString); Array.Resize(ref previousString, previousString.Length + 1); previousString[previousString.Length - 1] = previousString[0]; dictionaryForDecode.Add(index, previousString); @@ -171,6 +172,7 @@ private static bool DecodeFile(string fileName) var stringByIndex = dictionaryForDecode[input]; if (index != input) { + ArgumentNullException.ThrowIfNull(previousString); Array.Resize(ref previousString, previousString.Length + 1); previousString[previousString.Length - 1] = stringByIndex[0]; dictionaryForDecode.Add(index, previousString); diff --git a/LZW/TestLZW/TestLZW.cs b/LZW/TestLZW/TestLZW.cs index 4b93848..242673f 100644 --- a/LZW/TestLZW/TestLZW.cs +++ b/LZW/TestLZW/TestLZW.cs @@ -8,15 +8,9 @@ public class Tests public void TheLZWShouldWorkCorrectlyToReturnTheCorrectValueOnASimpleExample() { var (isCorrect, _) = LZWAlgorithm.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.txt"), "-c"); - if (!isCorrect ) - { - Assert.That(false, Is.EqualTo(!isCorrect)); - } + Assert.That(!isCorrect, Is.EqualTo(false)); (isCorrect, var _) = LZWAlgorithm.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.txt.zipped"), "-u"); - if (!isCorrect) - { - Assert.That(false, Is.EqualTo(!isCorrect)); - } + Assert.That(!isCorrect, Is.EqualTo(false)); string correctText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "correctTestAnElementaryExample.txt")); string fromLZWText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "testAnElementaryExample.txt")); Assert.That(correctText, Is.EqualTo(fromLZWText)); @@ -47,15 +41,9 @@ public void LZWShouldReturnFalseWhenReceivingAFileWithAnIncorrectParametr() public void TheLZWShouldReturnAnEmptyFileEmpty() { var (isCorrect, _) = LZWAlgorithm.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.txt"), "-c"); - if (!isCorrect) - { - Assert.That(false, Is.EqualTo(!isCorrect)); - } + Assert.That(!isCorrect, Is.EqualTo(false)); (isCorrect, var _) = LZWAlgorithm.LzwAlgorithm(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.txt.zipped"), "-u"); - if (!isCorrect) - { - Assert.That(false, Is.EqualTo(!isCorrect)); - } + Assert.That(!isCorrect, Is.EqualTo(false)); string fromLZWText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "emptyFile.txt")); string correctText = File.ReadAllText(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsForLZW", "correctEmptyFile.txt")); Assert.That(correctText, Is.EqualTo(fromLZWText)); From 911cae267f0eb5fb9b1bd05069c6864f042de313 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 26 May 2023 16:13:58 +0300 Subject: [PATCH 12/12] =?UTF-8?q?=D0=A0=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LZW/LZW/Bor.cs | 18 +++++++------- LZW/LZW/LZW.cs | 54 ++++++---------------------------------- LZW/LZW/Program.cs | 21 ++++++---------- LZW/TestsBor/TestsBor.cs | 4 +-- 4 files changed, 26 insertions(+), 71 deletions(-) diff --git a/LZW/LZW/Bor.cs b/LZW/LZW/Bor.cs index 66f2617..c4c1338 100644 --- a/LZW/LZW/Bor.cs +++ b/LZW/LZW/Bor.cs @@ -24,7 +24,7 @@ public class Bor var walker = root; int i = 0; int pointer = from; - int toFlow = -1; + int toSymbolCode = -1; bool isStringInBor = Contains(buffer, from, to); while (i < to - from + 1) { @@ -38,25 +38,25 @@ public class Bor { ++walker.Next[number].HowManyStringInDictionary; } - toFlow = walker.Flow; + toSymbolCode = walker.SymbolCode; walker = walker.Next[number]; pointer++; i++; } if (!walker.IsTerminal) { - walker.Flow = root.HowManyStringInDictionary; + walker.SymbolCode = root.HowManyStringInDictionary; root.HowManyStringInDictionary++; } if (!walker.IsTerminal) { walker.IsTerminal = true; - return (true, toFlow); + return (true, toSymbolCode); } else { - return (true, toFlow); + return (true, toSymbolCode); } } @@ -64,7 +64,7 @@ public class Bor /// /// Returns a stream by letter /// - public int ReturnFlowByCharArray(char[] buffer, int to = 0, int from = 0) + public int ReturnSymbolCodeByCharArray(char[] buffer, int to = 0, int from = 0) { if (buffer.Length == 0) { @@ -83,7 +83,7 @@ public int ReturnFlowByCharArray(char[] buffer, int to = 0, int from = 0) walker = walker.Next[number]; ++i; } - return walker.Flow; + return walker.SymbolCode; } /// @@ -132,12 +132,12 @@ private class BorElement public int HowManyStringInDictionary { get; set; } - public int Flow { get; set; } + public int SymbolCode { get; set; } public BorElement() { Next = new Dictionary(); - Flow = -1; + SymbolCode = -1; } } } diff --git a/LZW/LZW/LZW.cs b/LZW/LZW/LZW.cs index b82b4de..a1e4345 100644 --- a/LZW/LZW/LZW.cs +++ b/LZW/LZW/LZW.cs @@ -7,28 +7,6 @@ /// public static class LZWAlgorithm { - private static void ChangeFileNameToTheOriginalName(ref char[] newFile) - { - if (newFile.Length < 8) - { - throw new ArgumentException(); - } - Array.Resize(ref newFile, newFile.Length - 7); - } - - private static void ChangeFileNameToZipped(ref char[] newFile) - { - int sizeNewFile = newFile.Length; - Array.Resize(ref newFile, sizeNewFile + 7); - newFile[sizeNewFile] = '.'; - newFile[sizeNewFile + 1] = 'z'; - newFile[sizeNewFile + 2] = 'i'; - newFile[sizeNewFile + 3] = 'p'; - newFile[sizeNewFile + 4] = 'p'; - newFile[sizeNewFile + 5] = 'e'; - newFile[sizeNewFile + 6] = 'd'; - } - private static void AddAlphabetToBor(Bor bor) { var letter = new char[1]; @@ -41,12 +19,9 @@ private static void AddAlphabetToBor(Bor bor) private static bool CodeFile(string fileName, ref double compressionRatio) { - char[]? newFileArray = null; double sizeForCompressionRatio = 0; try { - newFileArray = new char[fileName.Length]; - Array.Copy(fileName.ToCharArray(), newFileArray, fileName.Length); FileInfo fileFromMain = new(fileName); sizeForCompressionRatio = fileFromMain.Length; } @@ -54,12 +29,7 @@ private static bool CodeFile(string fileName, ref double compressionRatio) { return false; } - ChangeFileNameToZipped(ref newFileArray); - string? newFile = new string(newFileArray); - if (newFile == null) - { - return false; - } + string newFile = fileName + ".zipped"; File.WriteAllText(newFile, string.Empty); @@ -82,8 +52,7 @@ private static bool CodeFile(string fileName, ref double compressionRatio) // Добавление потоков в файл int walker = 0; - int sizeText = textFromFile.Length; - var fstreamNew = new FileStream(newFile, FileMode.Append); + using var archivedFile = new FileStream(newFile, FileMode.Append); for (int i = 0; i < textFromFile.Length; i++) { if (!bor.Contains(textFromFile, walker, i)) @@ -91,15 +60,15 @@ private static bool CodeFile(string fileName, ref double compressionRatio) var (_, flow) = bor.Add(textFromFile, walker, i); walker = i; byte[] bytes = BitConverter.GetBytes(flow); - fstreamNew.WriteAsync(bytes, 0, bytes.Length); + archivedFile.WriteAsync(bytes, 0, bytes.Length); } } // Добавление последнего потока в файл - var flowLast = bor.ReturnFlowByCharArray(textFromFile, bufferIn.Length - 1, bufferIn.Length - 1); + var flowLast = bor.ReturnSymbolCodeByCharArray(textFromFile, bufferIn.Length - 1, bufferIn.Length - 1); byte[] bytesLast = BitConverter.GetBytes(flowLast); - fstreamNew.WriteAsync(bytesLast, 0, bytesLast.Length); - fstreamNew.Close(); + archivedFile.WriteAsync(bytesLast, 0, bytesLast.Length); + archivedFile.Close(); var file = new FileInfo(newFile.ToString()); double newSizeForCompressionRatio = file.Length; compressionRatio = newSizeForCompressionRatio / sizeForCompressionRatio; @@ -118,14 +87,7 @@ private static bool DecodeFile(string fileName) return false; } int i = 0; - var newFileArray = new char[fileName.Length]; - Array.Copy(fileName.ToCharArray(), newFileArray, fileName.Length); - ChangeFileNameToTheOriginalName(ref newFileArray); - string? newFile = new string(newFileArray); - if (newFile == null) - { - return false; - } + string newFile = fileName.Remove(fileName.Length - 7); File.WriteAllText(newFile, string.Empty); @@ -191,7 +153,7 @@ private static bool DecodeFile(string fileName) var stringByIndex = dictionaryForDecode[input]; previousString = stringByIndex; isFirst = false; - FileStream file = File.Open(newFile, FileMode.Append); + using FileStream file = File.Open(newFile, FileMode.Append); foreach (var symbol in stringByIndex) { file.WriteByte((byte)symbol); diff --git a/LZW/LZW/Program.cs b/LZW/LZW/Program.cs index 7c76a42..c3c8a86 100644 --- a/LZW/LZW/Program.cs +++ b/LZW/LZW/Program.cs @@ -1,17 +1,10 @@ -namespace LZW; +using LZW; -using System; -class Program +var (isCorrect, compressionRatio) = LZWAlgorithm.LzwAlgorithm(args[0], args[1]); +if (!isCorrect) { - public static void Main(string[] args) - { - var (isCorrect, compressionRatio) = LZWAlgorithm.LzwAlgorithm(args[0], args[1]); - if (!isCorrect) - { - Console.WriteLine("Problems..."); - return; - } - Console.WriteLine(compressionRatio); - } -} \ No newline at end of file + Console.WriteLine("Problems..."); + return; +} +Console.WriteLine(compressionRatio); \ No newline at end of file diff --git a/LZW/TestsBor/TestsBor.cs b/LZW/TestsBor/TestsBor.cs index 7198a7b..becd865 100644 --- a/LZW/TestsBor/TestsBor.cs +++ b/LZW/TestsBor/TestsBor.cs @@ -35,7 +35,7 @@ public void WhenAddingTheSymbolFlowInTheBorShouldBeCorrect() Setup(); bor.Add("a".ToCharArray(), 0, 0); bor.Add("b".ToCharArray(), 0, 0); - Assert.True(bor.ReturnFlowByCharArray("b".ToCharArray(), 0, 0) == 1, "Problems with the prefix test!"); + Assert.True(bor.ReturnSymbolCodeByCharArray("b".ToCharArray(), 0, 0) == 1, "Problems with the prefix test!"); } [Test] @@ -48,7 +48,7 @@ public void TheInitializedBorShouldBeEmpty() [Test] public void ThereShouldBeNoThreadsInTheCreatedBor() { - Assert.True(bor.ReturnFlowByCharArray("".ToCharArray(), 0, 0) == -1, "Problems with the prefix test!"); + Assert.True(bor.ReturnSymbolCodeByCharArray("".ToCharArray(), 0, 0) == -1, "Problems with the prefix test!"); } } \ No newline at end of file