Побитовая запись в файл - C#

Узнай цену своей работы

Формулировка задачи:

пытаюсь реализовать алгоритм Хаффмана и вот столкнулась с побитовыми операциями.. сколько не искала примеров никак не получается запихнуть полученный код в файл (точнее разбить его по 8 и запихнуть в байт) подскажите как это можно сделать вот код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO;
using System.Threading;
 
namespace HuffmanTest
{
 
    class Program
    {
        public class Node
        {
            public char Symbol { get; set; }
            public int Frequency { get; set; }
            public Node Right { get; set; }
            public Node Left { get; set; }
 
            public List<bool> Traverse(char symbol, List<bool> data)
            {
                // Leaf
                if (Right == null && Left == null)
                {
                    if (symbol.Equals(this.Symbol))
                    {
                        return data;
                    }
                    else
                    {
                        return null;
                    }
                }
                else
                {
                    List<bool> left = null;
                    List<bool> right = null;
 
                    if (Left != null)
                    {
                        List<bool> leftPath = new List<bool>();
                        leftPath.AddRange(data);
                        leftPath.Add(false);
 
                        left = Left.Traverse(symbol, leftPath);
                    }
 
                    if (Right != null)
                    {
                        List<bool> rightPath = new List<bool>();
                        rightPath.AddRange(data);
                        rightPath.Add(true);
                        right = Right.Traverse(symbol, rightPath);
                    }
 
                    if (left != null)
                    {
                        return left;
                    }
                    else
                    {
                        return right;
                    }
                }
            }
        }
        public class HuffmanTree
        {
            private List<Node> nodes = new List<Node>();
            public Node Root { get; set; }
            public Dictionary<char, int> Frequencies = new Dictionary<char, int>();
 
            public void Build(string source)
            {
                for (int i = 0; i < source.Length; i++)
                {
                    if (!Frequencies.ContainsKey(source[i]))
                    {
                        Frequencies.Add(source[i], 0);
                    }
 
                    Frequencies[source[i]]++;
                }
 
                foreach (KeyValuePair<char, int> symbol in Frequencies)
                {
                    nodes.Add(new Node() { Symbol = symbol.Key, Frequency = symbol.Value });
                }
 
                while (nodes.Count > 1)
                {
                    List<Node> orderedNodes = nodes.OrderBy(node => node.Frequency).ToList<Node>();
 
                    if (orderedNodes.Count >= 2)
                    {
                        // Take first two items
                        List<Node> taken = orderedNodes.Take(2).ToList<Node>();
 
                        // Create a parent node by combining the frequencies
                        Node parent = new Node()
                        {
                            Symbol = '*',
                            Frequency = taken[0].Frequency + taken[1].Frequency,
                            Left = taken[0],
                            Right = taken[1]
                        };
 
                        nodes.Remove(taken[0]);
                        nodes.Remove(taken[1]);
                        nodes.Add(parent);
                    }
 
                    this.Root = nodes.FirstOrDefault();
 
                }
 
            }
/*
            public BitArray Encode(string source)
            {
               List<bool> encodedSource = new List<bool>();
 
                for (int i = 0; i < source.Length; i++)
                {
                    List<bool> encodedSymbol = this.Root.Traverse(source[i], new List<byte>());
                    encodedSource.AddRange(encodedSymbol);
                }
 
                BitArray bits = new BitArray(encodedSource.ToArray());
 
                return bits;
            }*/
 
            public string Decode(BitArray bits)
            {
                Node current = this.Root;
                string decoded = "";
 
                foreach (bool bit in bits)
                {
                    if (bit)
                    {
                        if (current.Right != null)
                        {
                            current = current.Right;
                        }
                    }
                    else
                    {
                        if (current.Left != null)
                        {
                            current = current.Left;
                        }
                    }
 
                    if (IsLeaf(current))
                    {
                        decoded += current.Symbol;
                        current = this.Root;
                    }
                }
 
                return decoded;
            }
 
            public bool IsLeaf(Node node)
            {
                return (node.Left == null && node.Right == null);
            }
 
         /*   public void Print(Node R)
            {
                if (R != null) 
                {
                    if (R.Symbol != '*') { Console.WriteLine(R.Symbol); Console.WriteLine(R.Frequency); }
                    else if (R.Right != null) { Print(R.Right); }
                    else if (R.Left != null) { Print(R.Left); }
                }
            }
            */
        }
        static void Main(string[] args)
        {
            //  string input = "кот ломом колол слона";
            //HuffmanTree huffmanTree = new HuffmanTree();
            //_____
            
                List<Node> nodes = new List<Node>(); // для сортировки
                Node Root = null; // дерево
                Dictionary<char, int> Frequencies = new Dictionary<char, int>(); // словарь
                //_____
                char input;// строка для чтения
 
            //частоты и составление cловаря    
            using (StreamReader sr = new StreamReader("file.txt"))
                {
                    
                    while (sr.Peek() >= 0)
                    {
                        input = (char)sr.Read();
                        Console.Write(input);
 
                        if (!Frequencies.ContainsKey(input))
                        {
                            Frequencies.Add(input, 0);
                        }
 
                        Frequencies[input]++;
                    }
                    sr.Close();
                }
            
                // печать словаря
                 /*foreach (KeyValuePair<char, int> s in Frequencies)
                 {
                     Console.WriteLine(s.Key);
                     Console.WriteLine(s.Value);
                 }*/
 
                // Build the Huffman tree
 
                // составление массива для сортировки
                foreach (KeyValuePair<char, int> symbol in Frequencies)
                {
                    nodes.Add(new Node() { Symbol = symbol.Key, Frequency = symbol.Value });
                }
 
                while (nodes.Count > 1)
                {
                    List<Node> orderedNodes = nodes.OrderBy(node => node.Frequency).ToList<Node>();
 
                    if (orderedNodes.Count >= 2)
                    {
                        // берем два наименьших
                        List<Node> taken = orderedNodes.Take(2).ToList<Node>();
 
                        // создаем родителя
                        Node parent = new Node()
                        {
                            Symbol = '*',
                            Frequency = taken[0].Frequency + taken[1].Frequency,
                            Left = taken[0],
                            Right = taken[1]
                        };
                        //удаляем два наименьших и записываем их родителя в массив
                        nodes.Remove(taken[0]);
                        nodes.Remove(taken[1]);
                        nodes.Add(parent);
                    }
                    // указатель на корень дерева
                    Root = nodes.FirstOrDefault();
 
                }
            
            // Encode
            
            List<bool> encodedSource = new List<bool>();
 
                using (StreamReader sr = new StreamReader("file.txt"))
                {
                    while (sr.Peek() >= 0)
                   {
                       input = (char)sr.Read();
                        List<bool> encodedSymbol = Root.Traverse(input, new List<bool>());
                   encodedSource.AddRange(encodedSymbol);
                    }
                    sr.Close();
                }
 
                BitArray bits = new BitArray(encodedSource.ToArray());
            //вывод кода
            /*
        Console.Write("Encoded: ");
        foreach (bool bit in bits)
        {
            Console.Write((bit ? 1 : 0));
        }
        Console.WriteLine();*/
            
             Thread.Sleep(5000);
        }
    }
}

Решение задачи: «Побитовая запись в файл»

textual
Листинг программы
using MS.Utility; 
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic; 
using System.Windows;
using System.Diagnostics; 
  
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID; 
 
namespace MS.Internal.Ink
{
    /// <summary> 
    /// A stream-like writer for packing bits into a byte buffer
    /// </summary> 
    /// <remarks>This class is to be used with the BitStreamReader for reading
    /// and writing bytes. Note that the bytes should be read in the same order
    /// and lengths as they were written to retrieve the same values.
    /// See remarks in BitStreamReader regarding compatibility with the native C++ 
    /// BitStream class.</remarks>
    internal class BitStreamWriter 
    { 
        /// <summary>
        /// Create a new bit writer that writes to the target buffer 
        /// </summary>
        /// <param name="bufferToWriteTo">
        internal BitStreamWriter(List<byte> bufferToWriteTo)
        { 
            if (bufferToWriteTo == null)
            { 
                throw new ArgumentNullException("bufferToWriteTo"); 
            }
            _targetBuffer = bufferToWriteTo; 
        }
 
        /// <summary>
        /// Writes the count of bits from the int to the left packed buffer 
        /// </summary>
        /// <param name="bits"> 
        /// <param name="countOfBits"> 
        internal void Write(uint bits, int countOfBits)
        { 
            // validate that a subset of the bits in a single byte are being written
            if (countOfBits <= 0 || countOfBits > Native.BitsPerInt)
                throw new ArgumentOutOfRangeException("countOfBits", countOfBits, SR.Get(SRID.CountOfBitsOutOfRange));
  
 
            // calculate the number of full bytes 
            //   Example: 10 bits would require 1 full byte 
            int fullBytes = countOfBits / Native.BitsPerByte;
  
            // calculate the number of bits that spill beyond the full byte boundary
            //   Example: 10 buttons would require 2 extra bits (8 fit in a full byte)
            int bitsToWrite = countOfBits % Native.BitsPerByte;
  
            for (; fullBytes >= 0; fullBytes--)
            { 
                byte byteOfData = (byte)(bits >> (fullBytes * Native.BitsPerByte)); 
                //
                // write 8 or less bytes to the bitwriter 
                // checking for 0 handles the case where we're writing 8, 16 or 24 bytes
                // and bitsToWrite is initialize to zero
                //
                if (bitsToWrite > 0) 
                {
                    Write(byteOfData, bitsToWrite); 
                } 
                if (fullBytes > 0)
                { 
                    bitsToWrite = Native.BitsPerByte;
                }
            }
        } 
 
        /// <summary> 
        /// Writes the count of bits from the int to the buffer in reverse order 
        /// </summary>
        /// <param name="bits"> 
        /// <param name="countOfBits">
        internal void WriteReverse(uint bits, int countOfBits)
        {
            // validate that a subset of the bits in a single byte are being written 
            if (countOfBits <= 0 || countOfBits > Native.BitsPerInt)
                throw new ArgumentOutOfRangeException("countOfBits", countOfBits, SR.Get(SRID.CountOfBitsOutOfRange)); 
  
            // calculate the number of full bytes
            //   Example: 10 bits would require 1 full byte 
            int fullBytes = countOfBits / Native.BitsPerByte;
 
            // calculate the number of bits that spill beyond the full byte boundary
            //   Example: 10 buttons would require 2 extra bits (8 fit in a full byte) 
            int bitsToWrite = countOfBits % Native.BitsPerByte;
            if (bitsToWrite > 0) 
            { 
                fullBytes++;
            } 
            for (int x = 0; x < fullBytes; x++)
            {
                byte byteOfData = (byte)(bits >> (x * Native.BitsPerByte));
                Write(byteOfData, Native.BitsPerByte); 
            }
        } 
  
        /// <summary>
        /// Write a specific number of bits from byte input into the stream 
        /// </summary>
        /// <param name="bits">The byte to read the bits from
        /// <param name="countOfBits">The number of bits to read
        internal void Write(byte bits, int countOfBits) 
        {
            // validate that a subset of the bits in a single byte are being written 
            if (countOfBits <= 0 || countOfBits > Native.BitsPerByte) 
                throw new ArgumentOutOfRangeException("countOfBits", countOfBits, SR.Get(SRID.CountOfBitsOutOfRange));
  
            byte buffer;
                // if there is remaining bits in the last byte in the stream
                //      then use those first
            if (_remaining > 0) 
            {
                // retrieve the last byte from the stream, update it, and then replace it 
                buffer = _targetBuffer[_targetBuffer.Count - 1]; 
                    // if the remaining bits aren't enough then just copy the significant bits
                    //      of the input into the remainder 
                if (countOfBits > _remaining)
                {
                    buffer |= (byte)((bits & (0xFF >> (Native.BitsPerByte - countOfBits))) >> (countOfBits - _remaining));
                } 
                    // otherwise, copy the entire set of input bits into the remainder
                else
                { 
                    buffer |= (byte)((bits & (0xFF >> (Native.BitsPerByte - countOfBits))) << (_remaining - countOfBits));
                } 
                _targetBuffer[_targetBuffer.Count - 1] = buffer;
            }
 
            // if the remainder wasn't large enough to hold the entire input set 
            if (countOfBits > _remaining)
            { 
                  // then copy the uncontained portion of the input set into a temporary byte 
                _remaining = Native.BitsPerByte - (countOfBits - _remaining);
                unchecked // disable overflow checking since we are intentionally throwing away 
                            //  the significant bits
                {
                    buffer = (byte)(bits << _remaining);
                } 
                    // and add it to the target buffer
                _targetBuffer.Add(buffer); 
            } 
            else
            { 
                // otherwise, simply update the amount of remaining bits we have to spare
                _remaining -= countOfBits;
            }
        } 
 
  
        // the buffer that the bits are written into 
        private List<byte> _targetBuffer = null;
  
        // number of free bits remaining in the last byte added to the target buffer
        private int _remaining = 0;
    }
} 
 
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

9   голосов , оценка 3.889 из 5