霍夫曼编码.二进制文本

本文关键字:文本 二进制 编码 霍夫曼 | 更新日期: 2023-09-27 18:30:45

我需要将编码的文本保存到二进制文件中。用BinaryWriter".bin",用BinaryReader读取。

使用霍夫曼编码对文本和字符进行编码,然后我使字符串生成器更易于阅读,最后我得到了:

A:1111;l:1011;a:00; :01;m:1010;k:100;o:1110;t:1100;e:11010;.:11011;
111110110001101000011001110110000010001100111011000110100001111110111101011011

当我以这种方式将其保存到二进制文件时:

(BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create)))
            foreach (var bit in binaryString)
                writer.Write(bit);

通过记事本打开.bin文件,它会显示全文。编码。我需要让它不可读。例如,如果您通过记事本在旧系统中打开.exe,它会显示随机字符,例如 [、[] ##$# $# #%$^$ ^&% 或类似的东西。

我该怎么做?

我还需要读取该二进制文件并对其进行解码。读数:

var bits = new List<byte>();
        int position = 0,
            length;
        using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open)))
        {
            length = (int)reader.BaseStream.Length;
            while (position < length)
            {
                bits.Add(reader.ReadByte());
                position++;
            }
        }

和解码:

Console.WriteLine("'nDekodujemy!'n");
        int lineFeed = 0x0a,
            semicolon = 0x3b,
            colon = 0x3a;

        List<byte> structBits = new List<byte>();
        List <byte> textBits = new List<byte>();
        bool isStructBits = true;
        foreach(var bit in bits)
        {
            if (bit == lineFeed)
            {
                isStructBits = false;
                continue;
            }
            if (isStructBits)
                structBits.Add(bit);
            else
                textBits.Add(bit);
        }
        Console.Write("Zdekodowana struktura: ");
        foreach (var bit in structBits)
            Console.Write((char)bit);
        Console.Write("'nZakodowany tekst: ");
        foreach (var bit in textBits)
            Console.Write((char)bit);
        var charactersMap = new Dictionary<char, string>();
        Console.WriteLine("'nDekodowanie struktury!");
        {
            bool isKey = true, isValue = false;
            char key = ' ';
            string value = "";
            foreach (var bit in structBits)
            {
                Console.WriteLine("Key: {0}", key);
                if (isKey)
                {
                    if (!charactersMap.ContainsKey((char)bit))
                    {
                        key = (char)bit;
                        isKey = false;
                    }
                }
                if (bit == colon)
                {
                    isValue = true;
                    continue;
                }
                if (bit == semicolon)
                {
                    isValue = false;
                    isKey = true;
                    charactersMap.Add(key, value);
                    value = "";
                }
                if (isValue)
                {
                    value += (char)bit;
                }
            }
        }
        Console.WriteLine("'nKluczy: {0}'nZdekodowane klucze:", charactersMap.Count);
        foreach (var key in charactersMap.Keys)
            Console.WriteLine("{0} = {1}", key, charactersMap[key]);

        Console.WriteLine("'nDekodowanie tekstu!");
        string decodedText = "";
        string temp = "";
        foreach (var bit in textBits)
        {
            Console.WriteLine("Bit: {0}", (char)bit);
            Console.WriteLine("Temp: {0}", temp);
            temp += (char)bit;
            foreach (var key in charactersMap.Keys)
                if (charactersMap[key] == temp)
                {
                    decodedText += key;
                    temp = "";
                    break;
                }
        }
        Console.WriteLine("'n'nZdekodowano: {0}", decodedText);

有人可以帮忙吗?

霍夫曼编码.二进制文本

如果我清楚地理解您要做什么,那么您正在将编码消息的每个位写入整个字节,但您想将它们写入位。因此,在将它们写入文件之前,您应该将此位打包成字节。在构建二进制字符串的位置,您应该将每个 8 位合并到一个字节中(使用位操作)。

假设binaryString属于string类型,您可以使用如下所示的方法将其转换为byte 的集合:

public static IEnumerable<byte> AsHuffmanCode(this string source)
{
    const int BitsPerByte = 8;
    const int LastBit = 7;
    byte huffmanByte = 0;
    for (var index = 0; index < source.Length; index++)
    {
        var bit = source[index] == '0' ? 0 : 1;
        var bitPosition = index % BitsPerByte;
        huffmanByte |= (byte)(bit << bitPosition);
        if (bitPosition == LastBit)
        {
            yield return huffmanByte;
            huffmanByte = 0;
        }
    }
}

像这样使用它:

using (var writer = new BinaryWriter(File.Open(path, FileMode.Create)))
{
    foreach (var huffmanByte in binaryString.AsHuffmanCode())
        writer.Write(huffmanByte);
}

有关正在运行的版本,请参阅此 .NET 小提琴。

基本思想是读取char char的字符串,累积字符的位值,并在每 8 个字符后返回该累积值。累加是通过对位值进行 OR 运算来实现的,每个位值根据其在字符串中的位置进行移位。

byte解码为string应该是直截了当的。只需执行反向操作即可。

请注意,此方法不执行任何错误检查。