//формируем коллекцию нод с указанием их "веса", для последующей постройки дерева
 public BinaryTree(FrequencyTable frequency)
 {
     nodeList = new List <TreeNode>();
     for (short i = 0; i < frequency.Length; i++)
     {
         if (frequency[i] > 0)
         {
             nodeList.Add(new TreeNode(frequency[i], (byte)i));
         }
     }
     nodeList.Sort();
     BuildTree();
 }
        //кодирование знака в биты, возвращаем биты в буфере и количество бит в результате
        public Dictionary <byte, short[]> GetCodeTable(FrequencyTable frequency)
        {
            Stack treePath = new Stack(256);
            //в path хранится путь до значения представляющий собой двоичный код байта
            Dictionary <byte, short[]> codeTable = new Dictionary <byte, short[]>();

            for (short i = 0; i < frequency.Length; i++)
            {
                if (frequency[i] > 0)
                {
                    SearchNode(treePath, nodeList[0], -1, (byte)i);
                    short[] dump        = treePath.GetDump(out short length);
                    short[] resizedDump = new short[length];
                    for (short t = 0; t < length; t++)
                    {
                        resizedDump[t] = dump[t];
                    }
                    codeTable.Add((byte)i, resizedDump);
                    treePath.Reset();
                }
            }
            //возвращаем таблицу с кодами
            return(codeTable);
        }
Exemple #3
0
        public static int Unpacking(string inputFilePath)
        {
            FileOperation inputFile;

            if (File.Exists(inputFilePath))
            {
                inputFile = new FileOperation(inputFilePath, true);
            }
            else
            {
                return(-1);
            }

            int bytesRead;

            byte[] endBytes = new byte[1];                   //получаем число байт в конце
            bytesRead = inputFile.ReadFile(endBytes, 1);
            FrequencyTable frequency = new FrequencyTable(); //получаем таблицу частот

            byte[] buf = new byte[2048];
            if ((bytesRead = inputFile.ReadFile(buf, 2048)) < 2048)
            {
                return(-1);
            }
            for (short i = 0; i < 256; i++)
            {
                frequency[i] = BitConverter.ToInt64(buf, i * sizeof(long));
            }

            //создаем дерево
            BinaryTree tree = new BinaryTree(frequency);

            //распаковываем
            FileOperation outputFile = new FileOperation(inputFilePath.Substring(0, inputFilePath.Length - 4), false); //убираем расширение .pac

            int outPos = 0, outVal;

            buf = new byte[size];
            byte[] outBuf = new byte[size];

            System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch(); //debug
            timer.Start();                                                           //debug

            bytesRead = inputFile.ReadFile(buf, size);
            while (bytesRead > 0)
            {
                int emptyBits = endBytes[0] * inputFile.EndOfFile();
                for (short i = 0; i < bytesRead * 8 - emptyBits; i++) //нумеруем _биты_
                {
                    byte value = buf[i >> 3];
                    byte bit   = (byte)(((buf[i >> 3] & 1 << (7 - i % 8)) >= 1) ? 1 : 0); //получаем значение бита под номером i
                    outVal = tree.Decode(bit);                                            //поочередно отправляем биты расшифровщику. если результат положительный - мы получили значение
                    if (outVal >= 0)
                    {
                        outBuf[outPos] = (byte)outVal;
                        outPos++;
                        if (outPos >= size)
                        {
                            outPos = 0;
                            outputFile.WriteFile(outBuf, size);
                        }
                    }
                }
                bytesRead = inputFile.ReadFile(buf, size);
            }
            //записываем оставшиеся байты, закрываем файлы
            if (outPos > 0)
            {
                outputFile.WriteFile(outBuf, outPos);
            }

            timer.Stop();                                                                                                 //debug
            float ms = timer.ElapsedMilliseconds;                                                                         //debug

            Console.WriteLine("Average unpacking speed: " + (int)((inputFile.GetPos() / 1024) / (ms / 1000)) + " kb\\s"); //debug

            outputFile.CloseFile();
            inputFile.CloseFile();
            return(1);
        }
Exemple #4
0
        const int size = 32; //size < 256
        public static int Packing(string inputFilePath)
        {
            //открываем упаковываемый файл
            FileOperation InputFile;

            if (File.Exists(inputFilePath))
            {
                InputFile = new FileOperation(inputFilePath, true);
            }
            else
            {
                return(-1);
            }

            //создаем таблицу частот
            int bytesRead;

            byte[]         buf       = new byte[size];
            FrequencyTable frequency = new FrequencyTable();

            while ((bytesRead = InputFile.ReadFile(buf, size)) > 0)
            {
                for (int i = 0; i < bytesRead; i++)
                {
                    frequency.Add(buf[i]);
                }
            }

            //строим бинарное дерево и получаем таблицу кодов
            BinaryTree tree = new BinaryTree(frequency);
            Dictionary <byte, short[]> codeTable = tree.GetCodeTable(frequency);

            //открываем файлы, пишем таблицу частот
            InputFile.Reset();
            FileOperation outputFile = new FileOperation(inputFilePath + ".pac", false);

            outputFile.WriteFile(new byte[] { 0 }, 1);   //резерв места под число пустых бит в конце

            for (short i = 0; i < frequency.Length; i++) //записываем таблицу частот
            {
                outputFile.WriteFile(BitConverter.GetBytes(frequency[i]), sizeof(long));
            }


            //упаковываем
            int outPos = 0;               //текущий индекс в выходном массиве в _битах_

            byte[] outBuf = new byte[32]; //выходной массив
            bytesRead = InputFile.ReadFile(buf, size);
            while (bytesRead > 0)
            {
                for (byte i = 0; i < bytesRead; i++)
                {
                    byte value = buf[i];
                    for (byte t = 0; t < codeTable[value].Length; t++) //длина массива для каждого символа получаемого из buf
                    {
                        outBuf[outPos / 8] |= (byte)(codeTable[value][t] * Math.Pow(2, 7 - outPos % 8));
                        outPos++;
                        if (outPos >= 32 * 8)
                        {
                            outputFile.WriteFile(outBuf, 32);
                            outPos = 0;
                            Array.Clear(outBuf, 0, 32);
                            //запись в файл
                        }
                    }
                }
                bytesRead = InputFile.ReadFile(buf, size);
            }
            if (outPos > 0) //запись оставшихся бит
            {
                outputFile.WriteFile(outBuf, outPos / 8 + ((outPos % 8 > 0) ? 1 : 0));
            }
            outputFile.Reset();
            outputFile.WriteFile(new byte[] { (byte)((8 - outPos % 8) % 8) }, 1); //записываем количество пустых бит в конце
            outputFile.CloseFile();
            InputFile.CloseFile();

            return(1);
        }