1+ namespace LZW ;
2+
3+ using System ;
4+ using System . IO ;
5+ using Bor ;
6+
7+ /// <summary>
8+ /// A class representing the LZW algorithm
9+ /// </summary>
10+ public class LZW
11+ {
12+ //A function for determining the number of bytes needed to store a number
13+ private static int NumberOfBytes ( int number )
14+ {
15+ if ( number < 256 )
16+ {
17+ return 1 ;
18+ }
19+ if ( number < 65536 )
20+ {
21+ return 2 ;
22+ }
23+ if ( number < 16777216 )
24+ {
25+ return 3 ;
26+ }
27+ return 4 ;
28+ }
29+
30+ /// <summary>
31+ /// Function for file compression
32+ /// </summary>
33+ /// <param name="pathToFileToCompress">The path to the file to compress</param>
34+ public static void CompressFile ( string pathToFileToCompress )
35+ {
36+
37+ string fileName = Path . GetFileNameWithoutExtension ( pathToFileToCompress ) ;
38+ fileName = $ "{ pathToFileToCompress } ..//..//{ fileName } .zipped";
39+
40+ // Name of the compressed file
41+ using FileStream fs = new ( fileName , FileMode . Create ) ;
42+
43+ // Reading all bytes from a file
44+ var stringToConvert = File . ReadAllBytes ( pathToFileToCompress ) ;
45+
46+ // Creating bor
47+ Bor bor = new ( ) ;
48+
49+ for ( int i = 0 ; i < stringToConvert . Length ; i ++ )
50+ {
51+ // If the byte is contained in the bor
52+ if ( bor . Contains ( stringToConvert [ i ] ) )
53+ {
54+ // Moving on to the next byte
55+ bor . MoveIntoDesiredNode ( stringToConvert [ i ] ) ;
56+ }
57+ // Otherwise, we add it to the bor
58+ else
59+ {
60+ // Taking the idex from the parent vertex and encode it
61+ var bytes = BitConverter . GetBytes ( bor . GetCode ( ) ) ;
62+
63+ // Cut off the extra bytes
64+ // The required number of bytes is selected according to the size of the bor
65+ // Since among the numbers that need to be encoded there may be a bor size (index of the maximum vertex),
66+ // the number of bytes to store depends on the size of the bor.
67+ // Even a number requires fewer bytes,
68+ // it is written in a large number of bytes so that it can be decoded later.
69+ Array . Resize ( ref bytes , NumberOfBytes ( bor . Size - 1 ) ) ;
70+ bor . Add ( stringToConvert [ i ] ) ;
71+ fs . Write ( bytes ) ;
72+
73+ // Going back to the last vertex
74+ i -- ;
75+ }
76+ }
77+
78+ // The last bytes that are already in the dictionary and that are not written in the loop
79+ var newbytes = BitConverter . GetBytes ( bor . GetCode ( ) ) ;
80+ Array . Resize ( ref newbytes , NumberOfBytes ( bor . Size ) ) ;
81+ fs . Write ( newbytes ) ;
82+ }
83+
84+ public static void DecompressFile ( string pathToFile )
85+ {
86+
87+ string fileName = Path . GetFileNameWithoutExtension ( pathToFile ) ;
88+ fileName = $ "{ pathToFile } ..//..//{ fileName } ";
89+
90+ // Create file
91+ using FileStream fs = new ( fileName , FileMode . Create ) ;
92+
93+ // Reading all bytes from a file
94+ byte [ ] stringToConvert = File . ReadAllBytes ( pathToFile ) ;
95+
96+ // Dictionary for decoding
97+ var dictionary = new Dictionary < int , byte [ ] > ( ) ;
98+
99+ for ( int i = 0 ; i < 256 ; i ++ )
100+ {
101+ int index = 0 ;
102+ var byteArray = BitConverter . GetBytes ( i ) ;
103+ for ( int l = 0 ; l < byteArray . Length ; l ++ )
104+ {
105+ if ( l == 1 )
106+ {
107+ index = l ;
108+ }
109+ }
110+ dictionary . Add ( i , byteArray [ 0 ..index ] ) ;
111+ }
112+
113+ int rightBorder = 0 ;
114+ int leftBorder = 0 ;
115+ bool flag = false ;
116+
117+ while ( leftBorder < stringToConvert . Length )
118+ {
119+ // The right border of the current subarray
120+ rightBorder = leftBorder + NumberOfBytes ( dictionary . Count - 1 ) - 1 ;
121+
122+ // If the right border has gone beyond the edge, then we will make it the last byte
123+ rightBorder = rightBorder > stringToConvert . Length - 1 ? stringToConvert . Length - 1 : rightBorder ;
124+
125+
126+ if ( leftBorder > stringToConvert . Length - 1 )
127+ {
128+ break ;
129+ }
130+
131+ // Converting bytes to int
132+ var bytes = new byte [ 4 ] ;
133+ Array . Copy ( stringToConvert , leftBorder , bytes , 0 , NumberOfBytes ( dictionary . Count - 1 ) ) ;
134+ leftBorder = rightBorder + 1 ;
135+ int answer = BitConverter . ToInt32 ( bytes ) ;
136+
137+ // If it is the first number
138+ if ( ! flag )
139+ {
140+ flag = true ;
141+ }
142+
143+ // Otherwise, we concatenate the last element with the first byte of the current one
144+ else
145+ {
146+ var newArray = new byte [ dictionary [ dictionary . Count - 1 ] . Length + 1 ] ;
147+ Array . Copy ( dictionary [ dictionary . Count - 1 ] , newArray , dictionary [ dictionary . Count - 1 ] . Length ) ;
148+ newArray [ newArray . Length - 1 ] = dictionary [ answer ] [ 0 ] ;
149+ // Changing the value in the dictionary to the value we need
150+ dictionary [ dictionary . Count - 1 ] = newArray ;
151+ }
152+
153+ // Adding a new element to the dictionary
154+ dictionary . Add ( dictionary . Count , dictionary [ answer ] ) ;
155+ fs . Write ( dictionary [ answer ] ) ;
156+ }
157+ }
158+ }
0 commit comments