澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

澳门新萄京官方网站:拍卖依附比特流的数码,

2019-08-17 作者:www.8455.com   |   浏览(147)

使用C#处理基于比特流的数据

 

使用C#处理基于比特流的数据,

专题:ASCII, Unicode & UTF-8 (in Python)

Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分。文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示。Python 3不会以任意隐式的方式混用strbytes,你不能拼接字符串和字节流,也无法在字节流里搜索字符串(反之亦然),也不能将字符串传入参数为字节流的函数(反之亦然)。

0x00 起因

最近需要处理一些基于比特流的数据,计算机处理数据一般都是以byte(8bit)为单位的,使用BinaryReader读取的数据也是如此,即使读取bool型也是一个byte。不过借助于C#基础类库中提供的一些方法,也实现了对基于比特的数据的读取。任务完成后觉得基于比特的数据挺有意思,自己试了下用7比特和6比特编码常用ASCII字符。最后把一点新的写成博客,一方面做个记录,另一方面希望对有类似需求的园友有所帮助。

使用C#处理基于比特流的数据

 

1.基本概念:

编码发展的历史

0x01 比特流数据的读取

假设我们有一个byte b = 35,而我们需要把其中的前4bit和后4bit分别读取为两个数字,那么应该怎么做呢。虽然没有在基础类库中找到现成的方法,但用二进制字符串中转一下,分两步也可以做到。

1、先把b表示为二进制字符串00100011

2、分别取其前后4bit转为数字,核心方法就是:

Convert.ToInt32("0010");

这样就实现了基于比特的数据读取了。

关于第一步中把byte转化为二进制字符串有很多种方法,

1、最简单的Convert.ToString(b,2)。不够8位就在高位用0补足。

2、也可以把byte分别与1,2,4,8 … 128做与运算,由低到高取出各位。

3、也可以把byte和32做与运算,然后把byte左移再次与128做与运算。

其中第一种方法会产生大量的字符串对象,在第2、3种方法没有找到太大区别,我选择的3,纯靠感觉。代码如下:

public static char[] ByteToBinString(byte b)
{
  var result = new char[8];
  for (int i = 0; i < 8; i  )
  {
    var temp = b & 128;
    result[i] = temp == 0 ? '0' : '1';
    b = (byte)(b << 1);
  }
  return result;
}

为了能将byte[]转化为二进制字符串,可以

Public string BitReader(byte[] data)
{
    BinString = new StringBuilder(data.Length * 8);
    for (int i = 0; i < data.Length; 
    {
         BinString.Append(ByteToBinString(data[i]));
    }
    return BinString.ToString();
}    

这样一来当拿到byte[]数据时,可以转换为二进制字符串保存起来,根据偏移的bit位置和bit长度从中读取二进制字符串,并保转换为bool,Int16,Int32等。基于这个思路,可以写一个BitReader类,其中用StringBuilder存储二进制字符串,并提供Read方法从二进制字符串中读取数据。为了能够更好的处理数据流,在此基础上添加一个Position记录当前偏移,当使用某些Read方法读取数据时,Position也会相应移动。例如使用ReadInt16读取数据,BitReader会从Position当前位置,读取16bit并转换为Int16返回,同时Position向后移动16bit。区分方式就是当读取数据时需要指定起始的偏移位置时,Position不移动,直接从当前Position读取时Position移动,BitReader类部分代码如下:

澳门新萄京官方网站 1澳门新萄京官方网站 2

 1 public class BitReader
 2 {
 3     public readonly StringBuilder BinString;
 4     public int Position { get; set; }
 5 
 6     public BitReader(byte[] data)
 7     {
 8         BinString = new StringBuilder(data.Length * 8);
 9         for (int i = 0; i < data.Length; i  )
10         {
11             BinString.Append(ByteToBinString(data[i]));
12         }
13         Position = 0;
14     }
15 
16     public byte ReadByte(int offset)
17     {
18         var bin = BinString.ToString(offset, 8);
19         return Convert.ToByte(bin, 2);
20     }
21 
22     public byte ReadByte()
23     {
24         var result = ReadByte(Position);
25         Position  = 8;
26         return result;
27     }
28 
29     public int ReadInt(int offset, int bitLength)
30     {
31         var bin = BinString.ToString(offset, bitLength);
32         return Convert.ToInt32(bin, 2);
33     }
34 
35     public int ReadInt(int bitLength)
36     {
37         var result = ReadInt(Position, bitLength);
38         Position  = bitLength;
39         return result;
40     }
41 
42     public static char[] ByteToBinString(byte b)
43     {
44         var result = new char[8];
45         for (int i = 0; i < 8; i  )
46         {
47             var temp = b & 128;
48             result[i] = temp == 0 ? '0' : '1';
49             b = (byte)(b << 1);
50         }
51         return result;
52      }
53 }

View Code

使用BitReader按照4bit从byte[] buff= {35,12};中读取数据可以这样:

var reader = new BitReader(buff); //二进制字符串为0010001100001100

var num1 = reader.ReadInt(4);   //从当前Position读取4bit为int,Position移动4bit,结果为2,当前Position=4

var num2 = reader.ReadInt(5,6);  //从偏移为5bit的位置读取6bit为int,Position不移动,结果为48,当前Position=4

var b = reader.ReadBool();  //从当前Position读取1bit为bool,Position移动1bit,结果为False,当前Position=5

0x00 起因

最近需要处理一些基于比特流的数据,计算机处理数据一般都是以byte(8bit)为单位的,使用BinaryReader读取的数据也是如此,即使读取bool型也是一个byte。不过借助于C#基础类库中提供的一些方法,也实现了对基于比特的数据的读取。任务完成后觉得基于比特的数据挺有意思,自己试了下用7比特和6比特编码常用ASCII字符。最后把一点新的写成博客,一方面做个记录,另一方面希望对有类似需求的园友有所帮助。

(1)字符集:已编号字符的有序集合,包括字符编号和字符,对计算机没有直接意义

在谈bytesstr之前,需要先说说关于编码是如何发展的。。

0x02 比特流数据的写入

把数据写入比特流就是一个相反的过程,我们用BitWriter类实现,在其中存储StringBuilder保存二进制字符串,当写入数据时,需要传入数据并指定保存这个数据所需要的bit数。当写入完毕后可以将StringBuilder中保存的二进制字符串按照8bit转换为byte[]并返回。BitWriter的核心部分如下:

澳门新萄京官方网站 3澳门新萄京官方网站 4

 1 public class BitWriter
 2 {
 3     public readonly StringBuilder BinString;
 4 
 5     public BitWriter()
 6     {
 7         BinString = new StringBuilder();
 8     }
 9 
10     public BitWriter(int bitLength)
11     {
12         var add = 8 - bitLength % 8;
13         BinString = new StringBuilder(bitLength   add);
14     }
15 
16     public void WriteByte(byte b, int bitLength=8)
17     {
18         var bin = Convert.ToString(b, 2);
19         AppendBinString(bin, bitLength);
20     }
21 
22     public void WriteInt(int i, int bitLength)
23     {
24         var bin = Convert.ToString(i, 2);
25         AppendBinString(bin, bitLength);
26     }
27 
28     public void WriteChar7(char c)
29     {
30         var b = Convert.ToByte(c);
31         var bin = Convert.ToString(b, 2);
32         AppendBinString(bin, 7);
33     }
34 
35     public byte[] GetBytes()
36     {
37         Check8();
38         var len = BinString.Length / 8;
39         var result = new byte[len];
40 
41         for (int i = 0; i < len; i  )
42         {
43             var bits = BinString.ToString(i * 8, 8);
44             result[i] = Convert.ToByte(bits, 2);
45         }
46 
47         return result;
48     }
49 
50     public string GetBinString()
51     {
52         Check8();
53         return BinString.ToString();
54     }
55 
56 
57     private void AppendBinString(string bin, int bitLength)
58     {
59         if (bin.Length > bitLength)
60             throw new Exception("len is too short");
61         var add = bitLength - bin.Length;
62         for (int i = 0; i < add; i  )
63         {
64             BinString.Append('0');
65         }
66         BinString.Append(bin);
67     }
68 
69     private void Check8()
70     {
71         var add = 8 - BinString.Length % 8;
72         for (int i = 0; i < add; i  )
73         {
74             BinString.Append("0");
75         }
76     }
77 }

View Code

下面举个简单的例子:

var writer = new BitWriter();

writer.Write(12,5);  //把12用5bit写入,此时二进制字符串为:01100

writer.Write(8,16);  //把8用16bit写入,此时二进制字符串为:011000000000000001000

var result = writer.GetBytes(); //8bit对齐为011000000000000001000000
                                //返回结果为[96,0,64]

0x01 比特流数据的读取

假设我们有一个byte b = 35,而我们需要把其中的前4bit和后4bit分别读取为两个数字,那么应该怎么做呢。虽然没有在基础类库中找到现成的方法,但用二进制字符串中转一下,分两步也可以做到。

1、先把b表示为二进制字符串00100011

2、分别取其前后4bit转为数字,核心方法就是:

Convert.ToInt32("0010");

这样就实现了基于比特的数据读取了。

关于第一步中把byte转化为二进制字符串有很多种方法,

1、最简单的Convert.ToString(b,2)。不够8位就在高位用0补足。

2、也可以把byte分别与1,2,4,8 … 128做与运算,由低到高取出各位。

3、也可以把byte和32做与运算,然后把byte左移再次与128做与运算。

其中第一种方法会产生大量的字符串对象,在第2、3种方法没有找到太大区别,我选择的3,纯靠感觉。代码如下:

public static char[] ByteToBinString(byte b)
{
  var result = new char[8];
  for (int i = 0; i < 8; i  )
  {
    var temp = b & 128;
    result[i] = temp == 0 ? '0' : '1';
    b = (byte)(b << 1);
  }
  return result;
}

为了能将byte[]转化为二进制字符串,可以

Public string BitReader(byte[] data)
{
    BinString = new StringBuilder(data.Length * 8);
    for (int i = 0; i < data.Length; 
    {
         BinString.Append(ByteToBinString(data[i]));
    }
    return BinString.ToString();
}    

这样一来当拿到byte[]数据时,可以转换为二进制字符串保存起来,根据偏移的bit位置和bit长度从中读取二进制字符串,并保转换为bool,Int16,Int32等。基于这个思路,可以写一个BitReader类,其中用StringBuilder存储二进制字符串,并提供Read方法从二进制字符串中读取数据。为了能够更好的处理数据流,在此基础上添加一个Position记录当前偏移,当使用某些Read方法读取数据时,Position也会相应移动。例如使用ReadInt16读取数据,BitReader会从Position当前位置,读取16bit并转换为Int16返回,同时Position向后移动16bit。区分方式就是当读取数据时需要指定起始的偏移位置时,Position不移动,直接从当前Position读取时Position移动,BitReader类部分代码如下:

澳门新萄京官方网站 5 1 public class BitReader 2 { 3 public readonly StringBuilder BinString; 4 public int Position { get; set; } 5 6 public BitReader(byte[] data) 7 { 8 BinString = new StringBuilder(data.Length * 8); 9 for (int i = 0; i < data.Length; i ) 10 { 11 BinString.Append(ByteToBinString(data[i])); 12 } 13 Position = 0; 14 } 15 16 public byte ReadByte(int offset) 17 { 18 var bin = BinString.ToString(offset, 8); 19 return Convert.ToByte(bin, 2); 20 } 21 22 public byte ReadByte() 23 { 24 var result = ReadByte(Position); 25 Position = 8; 26 return result; 27 } 28 29 public int ReadInt(int offset, int bitLength) 30 { 31 var bin = BinString.ToString(offset, bitLength); 32 return Convert.ToInt32(bin, 2); 33 } 34 35 public int ReadInt(int bitLength) 36 { 37 var result = ReadInt(Position, bitLength); 38 Position = bitLength; 39 return result; 40 } 41 42 public static char[] ByteToBinString(byte b) 43 { 44 var result = new char[8]; 45 for (int i = 0; i < 8; i ) 46 { 47 var temp = b & 128; 48 result[i] = temp == 0 ? '0' : '1'; 49 b = (byte)(b << 1); 50 } 51 return result; 52 } 53 } View Code

使用BitReader按照4bit从byte[] buff= {35,12};中读取数据可以这样:

var reader = new BitReader(buff); //二进制字符串为0010001100001100

var num1 = reader.ReadInt(4);   //从当前Position读取4bit为int,Position移动4bit,结果为2,当前Position=4

var num2 = reader.ReadInt(5,6);  //从偏移为5bit的位置读取6bit为int,Position不移动,结果为48,当前Position=4

var b = reader.ReadBool();  //从当前Position读取1bit为bool,Position移动1bit,结果为False,当前Position=5

(2)编码方案:将字符集中的字符编号与二进制字符编码进行对应的映射

在计算机历史的早期,美国为代表的英语系国家主导了整个计算机行业,26个英文字母组成了多样的英语单词、语句、文章。因此,最早的字符编码规范是ASCII码,一种8位即1个字节的编码规范,它可以涵盖整个英语系的编码需要。

0x03 7比特字符编码

我们常用的ASCII字符是使用8bit编码的,但其中真正常用的那些字符只有7bit,最高位为0,所以对于一篇英文文章,我们可以使用7bit重新编码而不损失信息。编码的过程就是把文章字符依次取出,并用BitWriter按照7bit写入,最后获取新编码的byte[]。为了能够正确读取,我们规定当读到8bit数据为2时代表数据开始,接下来16bit数据为后面字符个数。代码如下:

    public byte[] Encode(string text)
    {
        var len = text.Length * 7   24;

        var writer = new BitWriter(len);
        writer.WriteByte(2);
        writer.WriteInt(text.Length, 16);

        for (int i = 0; i < text.Length; i  )
        {
            var b = Convert.ToByte(text[i]);
            writer.WriteByte(b, 7);
        }

        return writer.GetBytes();
    }

同样读取数据的时候,我们先寻找开始标识符,然后读出字符个数,根据字符个数依次读取字符,代码如下:

    public string Decode(byte[] data)
    {
        var reader = new BitReader(data);
        while (reader.Remain > 8)
        {
            var start = reader.ReadByte();
            if (start == 2)
                break;
        }
        var len = reader.ReadInt(16);
        var result = new StringBuilder(len);
        for (int i = 0; i < len; i  )
        {
            var b = reader.ReadInt(7);
            var ch = Convert.ToChar(b);
            result.Append(ch);
        }

        return result.ToString();
    }

由于数据头的存在,当编码几个字符时编码后数据反而更长了

 澳门新萄京官方网站 6

不过随着字符越多,编码后节省的越多。

 澳门新萄京官方网站 7

0x02 比特流数据的写入

把数据写入比特流就是一个相反的过程,我们用BitWriter类实现,在其中存储StringBuilder保存二进制字符串,当写入数据时,需要传入数据并指定保存这个数据所需要的bit数。当写入完毕后可以将StringBuilder中保存的二进制字符串按照8bit转换为byte[]并返回。BitWriter的核心部分如下:

澳门新萄京官方网站 8 1 public class BitWriter 2 { 3 public readonly StringBuilder BinString; 4 5 public BitWriter() 6 { 7 BinString = new StringBuilder(); 8 } 9 10 public BitWriter(int bitLength) 11 { 12 var add = 8 - bitLength % 8; 13 BinString = new StringBuilder(bitLength add); 14 } 15 16 public void WriteByte(byte b, int bitLength=8) 17 { 18 var bin = Convert.ToString(b, 2); 19 AppendBinString(bin, bitLength); 20 } 21 22 public void WriteInt(int i, int bitLength) 23 { 24 var bin = Convert.ToString(i, 2); 25 AppendBinString(bin, bitLength); 26 } 27 28 public void WriteChar7(char c) 29 { 30 var b = Convert.ToByte(c); 31 var bin = Convert.ToString(b, 2); 32 AppendBinString(bin, 7); 33 } 34 35 public byte[] GetBytes() 36 { 37 Check8(); 38 var len = BinString.Length / 8; 39 var result = new byte[len]; 40 41 for (int i = 0; i < len; i ) 42 { 43 var bits = BinString.ToString(i * 8, 8); 44 result[i] = Convert.ToByte(bits, 2); 45 } 46 47 return result; 48 } 49 50 public string GetBinString() 51 { 52 Check8(); 53 return BinString.ToString(); 54 } 55 56 57 private void AppendBinString(string bin, int bitLength) 58 { 59 if (bin.Length > bitLength) 60 throw new Exception("len is too short"); 61 var add = bitLength - bin.Length; 62 for (int i = 0; i < add; i ) 63 { 64 BinString.Append('0'); 65 } 66 BinString.Append(bin); 67 } 68 69 private void Check8() 70 { 71 var add = 8 - BinString.Length % 8; 72 for (int i = 0; i < add; i ) 73 { 74 BinString.Append("0"); 75 } 76 } 77 } View Code

下面举个简单的例子:

var writer = new BitWriter();

writer.Write(12,5);  //把12用5bit写入,此时二进制字符串为:01100

writer.Write(8,16);  //把8用16bit写入,此时二进制字符串为:011000000000000001000

var result = writer.GetBytes(); //8bit对齐为011000000000000001000000
                                //返回结果为[96,0,64]

(3)编码单位(码元):计算机处理字符时一次读取的二进制位数

编码是什么?编码就是把一个字符用一个二进制来表示。我们都知道,所有的东西,不管是英文、中文还是符号等等,最终存储在磁盘上都是01010101这类东西。在计算机内部,读取和存储数据归根结底,处理的都是0和1组成的比特流。问题来了,人类看不懂这些比特流,如何让这些010101对人类变得可读呢?于是出现了字符编码,它是个翻译机,在计算机内部某个地方,透明的帮我们将比特流翻译成人类可以直接理解的文字。对于一般用户,不需要知道这个过程是什么原理,是怎么执行的。但是对于程序员却是个必须搞清楚的问题。

0x04 6比特字符编码

从节省数据量的角度,如果允许损失部分信息,例如损失掉字母大小写,是可以进一步减少编码所需比特数的。26个字母 10个数字 符号,可以用6bit(64)进行编码。不过使用这种编码方式就不能用ASCII的映射方式了,我们可以自定义映射,例如0-10映射为十个数字等等,也可以使用自定义的字典,也就是传说中的密码本。经常看国产谍战片的应该都知道密码本吧,密码本就是一个字典,把字符进行重新映射获取明文,算是简单的单码替代,加密强度很小,在获取足量数据样本后基于统计很容易就能破解。下面我们就尝试基于自定义字典用6bit重新编码。

编码过程:

仍然像7bit编码那样写入消息头,然后依次取出文本中的字符,从字典中找到对应的数字,把数字按照6bit长度写入到BitWriter

    public byte[] Encode(string text)
    {
        text = text.ToUpper();
        var len = text.Length * 6   24;

        var writer = new BitWriter(len);
        writer.WriteByte(2);
        writer.WriteInt(text.Length, 16);

        for (int i = 0; i < text.Length; i  )
        {
            var index = GetChar6Index(text[i]);
            writer.WriteInt(index, 6);
        }

        return writer.GetBytes();

    }

    private int GetChar6Index(char c)
    {
        for (int i = 0; i < 64; i  )
        {
            if (Dict.Custom[i] == c)
                return i;
        }
        return 10; //return *
    }

解码过程:

解码也很简单,找到消息头,依次按照6bit读取数据,并从字典中找到对应的字符:

public string Decode(byte[] data)
{
    var reader = new BitReader(data);
    while(reader.Remain > 8)
    {
        var start = reader.ReadByte();
        if (start == 2)
            break;
    }
    var len = reader.ReadInt(16);
    var result = new StringBuilder(len);
    for (int i = 0; i < len; i  )
    {
        var index = reader.ReadInt(6);
        var ch = Dict.Custom[index];
        result.Append(ch);
    }

    return result.ToString();
}

同样一段文本用6bit自定义字典编码后数据长度更短了,不过损失了大小写和换行等格式。

澳门新萄京官方网站 9

如果从加密的角度考虑,可以设置N个自定义字典(假设10个),在消息头中用M bit(例如4bit)表示所用的字典。这样在每次编码时随机选择一个字典编码,解码时根据4bit数据选择相应字典解码,并且定时更换字典可以增大破解难度。感兴趣的园友可以自行尝试。

0x03 7比特字符编码

我们常用的ASCII字符是使用8bit编码的,但其中真正常用的那些字符只有7bit,最高位为0,所以对于一篇英文文章,我们可以使用7bit重新编码而不损失信息。编码的过程就是把文章字符依次取出,并用BitWriter按照7bit写入,最后获取新编码的byte[]。为了能够正确读取,我们规定当读到8bit数据为2时代表数据开始,接下来16bit数据为后面字符个数。代码如下:

    public byte[] Encode(string text)
    {
        var len = text.Length * 7   24;

        var writer = new BitWriter(len);
        writer.WriteByte(2);
        writer.WriteInt(text.Length, 16);

        for (int i = 0; i < text.Length; i  )
        {
            var b = Convert.ToByte(text[i]);
            writer.WriteByte(b, 7);
        }

        return writer.GetBytes();
    }

同样读取数据的时候,我们先寻找开始标识符,然后读出字符个数,根据字符个数依次读取字符,代码如下:

    public string Decode(byte[] data)
    {
        var reader = new BitReader(data);
        while (reader.Remain > 8)
        {
            var start = reader.ReadByte();
            if (start == 2)
                break;
        }
        var len = reader.ReadInt(16);
        var result = new StringBuilder(len);
        for (int i = 0; i < len; i  )
        {
            var b = reader.ReadInt(7);
            var ch = Convert.ToChar(b);
            result.Append(ch);
        }

        return result.ToString();
    }

由于数据头的存在,当编码几个字符时编码后数据反而更长了

 澳门新萄京官方网站 10

不过随着字符越多,编码后节省的越多。

澳门新萄京官方网站:拍卖依附比特流的数码,Computer科学。 澳门新萄京官方网站 11

(4)编码:按照编码方案,由字符转换而来的二进制数据。在已知编码单位和映射关系时,计算机可以对字符进行编码,也可以对编码进行解码

ASCII编码为例,它规定1个字节8个比特位代表1个字符的编码,也就是“00000000”这么宽,一个一个字节的解读。例如:01000001表示大写字母A,有时我们会“偷懒"的用65这个十进制来表示A在ASCII中的编码。8个比特位,可以没有重复的最多表示2的8次方(255)个字符。

0x05 写在最后

以上是我处理比特流数据的一点心得,仅仅是我自己能想到的一种方法,满足了我的需求。如果有更效率的更合理的方法,希望赐教。另外编码和解码的两个例子是出于有趣写着玩的,在实际中估计也用不到。毕竟现在带宽这么富裕,数据加密也有N种可靠的多的方式。

示例代码:

关于基于比特流的数据读取封装成了库

安装:PM> Install-Package Ayx.BitIO

项目地址:

 


更多内容欢迎访问我的博客:http://www.durow.vip

0x04 6比特字符编码

从节省数据量的角度,如果允许损失部分信息,例如损失掉字母大小写,是可以进一步减少编码所需比特数的。26个字母 10个数字 符号,可以用6bit(64)进行编码。不过使用这种编码方式就不能用ASCII的映射方式了,我们可以自定义映射,例如0-10映射为十个数字等等,也可以使用自定义的字典,也就是传说中的密码本。经常看国产谍战片的应该都知道密码本吧,密码本就是一个字典,把字符进行重新映射获取明文,算是简单的单码替代,加密强度很小,在获取足量数据样本后基于统计很容易就能破解。下面我们就尝试基于自定义字典用6bit重新编码。

编码过程:

仍然像7bit编码那样写入消息头,然后依次取出文本中的字符,从字典中找到对应的数字,把数字按照6bit长度写入到BitWriter

    public byte[] Encode(string text)
    {
        text = text.ToUpper();
        var len = text.Length * 6   24;

        var writer = new BitWriter(len);
        writer.WriteByte(2);
        writer.WriteInt(text.Length, 16);

        for (int i = 0; i < text.Length; i  )
        {
            var index = GetChar6Index(text[i]);
            writer.WriteInt(index, 6);
        }

        return writer.GetBytes();

    }

    private int GetChar6Index(char c)
    {
        for (int i = 0; i < 64; i  )
        {
            if (Dict.Custom[i] == c)
                return i;
        }
        return 10; //return *
    }

解码过程:

解码也很简单,找到消息头,依次按照6bit读取数据,并从字典中找到对应的字符:

public string Decode(byte[] data)
{
    var reader = new BitReader(data);
    while(reader.Remain > 8)
    {
        var start = reader.ReadByte();
        if (start == 2)
            break;
    }
    var len = reader.ReadInt(16);
    var result = new StringBuilder(len);
    for (int i = 0; i < len; i  )
    {
        var index = reader.ReadInt(6);
        var ch = Dict.Custom[index];
        result.Append(ch);
    }

    return result.ToString();
}

同样一段文本用6bit自定义字典编码后数据长度更短了,不过损失了大小写和换行等格式。

澳门新萄京官方网站 12

如果从加密的角度考虑,可以设置N个自定义字典(假设10个),在消息头中用M bit(例如4bit)表示所用的字典。这样在每次编码时随机选择一个字典编码,解码时根据4bit数据选择相应字典解码,并且定时更换字典可以增大破解难度。感兴趣的园友可以自行尝试。

2.ASCII、Unicode & UTF-8的实质:

后来,计算机得到普及,中文、日文、韩文等等国家的文字需要在计算机内表示,ASCII的255位远远不够,于是标准组织制定出了叫做UNICODE的万国码,它规定任何一个字符(不管哪国的)至少以2个字节表示,可以更多澳门新萄京官方网站:拍卖依附比特流的数码,Computer科学。。其中,英文字母就是用2个字节,而汉字是3个字节。这个编码虽然很好,满足了所有人的要求,但是它不兼容ASCII,同时还占用较多的空间和内存。因为,在计算机世界更多的字符是英文字母,明明可以1个字节就能够表示,非要用2个。

0x05 写在最后

以上是我处理比特流数据的一点心得,仅仅是我自己能想到的一种方法,满足了我的需求。如果有更效率的更合理的方法,希望赐教。另外编码和解码的两个例子是出于有趣写着玩的,在实际中估计也用不到。毕竟现在带宽这么富裕,数据加密也有N种可靠的多的方式。

示例代码:

使用C#处理基于比特流的数据 0x00 起因 最近需要处理一些基于比特流的数据,计算机处理数据一般都是以...

(1)ASCII:字符集以及编码方案,用0~127对128个字符做了编号,用8位作为编码单位,简单地把十进制编号转换而成的二进制数据作为编码

于是UTF-8编码应运而生,它规定英文字母系列用1个字节表示,汉字用3个字节表示等等。因此,它兼容ASCII,可以解码早期的文档。UTF-8很快就得到了广泛的应用。

(2)广义Unicode:

在编码的发展历程中,我国还创造了自己的编码方式,例如GBKGB2312BIG5。他们只局限于在国内使用,不被国外认可。在GBK编码中,中文汉字占2个字节。

①Unicode:字符集,以16位二进制数对世界上几乎全部字符做了编号

byte和str之间的异同:

②UTF-8:编码方案,以8位(一个字节)作为编码单位,按照一定规则(每字节前几位固定)将一个字符编码为1到4个字节

回到bytesstr的身上。bytes是一种比特流,它的存在形式是01010001110这种。我们无论是在写代码,还是阅读文章的过程中,肯定不会有人直接阅读这种比特流,它必须有一个编码方式,使得它变成有意义的比特流,而不是一堆晦涩难懂的01组合。因为编码方式的不同,对这个比特流的解读也会不同,对实际使用造成了很大的困扰。

3.ASCII、Unicode & UTF-8的应用背景:

1 s = '中文'
2 print(type(s))    #<class 'str'>
3 b = bytes(s,encoding='utf-8',errors='strict')
4 print(b)     #b'xe4xb8xadxe6x96x87'
5 print(type(b))    #<class 'bytes'>
6 s2 = str(b,encoding='utf-8',errors='strict')
7 print(s2)     #中文
8 print(type(s2))     #<class 'str'>

(1)ASCII:只能表示英文文本

从例子可以看出,s是个字符串类型。Python有个内置函数bytes()可以将字符串str类型转换成bytes类型,b实际上是一串01的组合,但为了在ide环境中让我们相对直观的观察,它被表现成了b'xe4xb8xadxe6x96x87'这种形式,开头的b表示这是一个bytes类型。xe4是十六进制的表示方式,它占用1个字节的长度,因此”中文“被编码成utf-8后,我们可以数得出一共用了6个字节,每个汉字占用3个,这印证了上面的论述。在使用内置函数bytes()的时候,必须明确encoding的参数,不可省略,**str()也类似。**

(2)Unicode:表示多语言文本,兼容ASCII

我们都知道,字符串类str里有一个encode()方法,它是从字符串向比特流的编码过程。而bytes类型恰好有个decode()方法,它是从比特流向字符串解码的过程。除此之外,我们查看Python源码会发现bytesstr拥有几乎一模一样的方法列表,最大的区别就是encodedecode

(3)UTF-8:传输、存储用Unicode表示的多语言文本,去除Unicode中的冗余部分

从实质上来说,字符串在磁盘上的保存形式也是01的组合,也需要编码解码。

4.Python描述:

总结:

(1)bytes和str类型:

1、在将字符串写入磁盘或者从磁盘读取字符串的时候,Python会自动的完成编码和解码的工作。

①bytes:编码比特流,如0101101000101101

2、在使用bytes()的时候,实际就是告诉Python,不需要Python帮你进行编码,你会手动对输入的字符串进行编码,并且可以指定编码格式。

②str:字符串,如’Python’

3、在Python 3中对byte和str进行了严格的区分,不能在需要byte类型参数的时候,使用str类型参数。

变量的类型可以用type()查看,或者以输出时是否带有b’’来区分

两种方式:

(2)encode和decode方法:

 1 #将str转换为byte
 2 unicode_string = '中文'
 3 print(type(unicode_string))   #<class 'str'>
 4 #第一种
 5 bytearray = unicode_string.encode()     #def encode(self, encoding='utf-8', errors='strict'),默认就是'utf-8'的编码方式
 6 print(bytearray)     #b'xe4xb8xadxe6x96x87'
 7 print(type(bytearray))    #<class 'bytes'>
 8 #第二种
 9 bytearray2 = bytes(unicode_string,encoding='utf-8',errors='strict')     #def __init__(self, value=b'', encoding=None, errors='strict')
10 print(bytearray2)      #b'xe4xb8xadxe6x96x87'
11 print(type(bytearray2))    #<class 'bytes'>
12 
13 #将byte转换为str
14 bytearray = b'xe4xb8xadxe6x96x87'
15 print(type(bytearray))   #<class 'bytes'>
16 #第一种
17 unicode_string = bytearray.decode()
18 print(unicode_string)    #中文
19 print(type(unicode_string))    #<class 'str'>
20 #第二种
21 unicode_string2 = str(bytearray,encoding='utf-8',errors='strict')
22 print(unicode_string2)    #中文
23 print(type(unicode_string2))    #<class 'str'>

①encode将str以声明的编码方案转换为bytes,也就是编码

参考:

②decode将bytes以声明的编码方案转换为str,也就是解码

Chown-Jane-Y

5.Python中的字符操作:

(1)在将字符串存入硬盘和从硬盘中读取字符串的过程中,自动进行编码和解码

(2)为了避免乱码问题,应坚持使用UTF-8方案

本文由澳门新萄京官方网站发布于www.8455.com,转载请注明出处:澳门新萄京官方网站:拍卖依附比特流的数码,

关键词: