Побитовая запись в файл - 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.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д