Ejemplo n.º 1
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);
        }