资源下载:
http://d.download.csdn.net/down/566609/KiteGirlFlashBit是我最想写而又一直没时间写的一个程序,今天一鼓作气把它捣鼓出来了。
这是在VB下实现对Bit操作的一组实用函数,是个把Byte肢解成若干Bit来操作的玩意儿,说它变态一点不过分。
这个程序看起来似乎有点吃饱了撑的,但实际上它相当有用。写它的动机来自于以VB编写哈夫曼编码/解码器和单片机应用的一些需求。VB下对Bit操作相当不方便,连移位命令都没有。而利用算数方法实现一些对Bit的操作在速度上实在难以忍受,而且代码及其冗长复杂。就这个程序本身来说,如果用纯算数方法实现,速度至少慢10倍,我是用一种比较缺德的查表法来实现的(将近9MB大的一个表,非常变态)。
至于它能做什么?比较典型的用途是做BASE64编码/解码器、哈夫曼编码/解码器,或者把信息藏在一个BMP文件像素的0位面里(据说本·拉登先生曾用这个办法通过互联网传递信息)。单色位图、采集点阵字库、GIF编码也会用到它。这个程序有Simple和Professional两种。功能、速度完全一样。两者区别是:
Simple没有真正的计算函数,纯粹是查表,不能自己生成FlashBit_BSL_Buffer.dat;
Professional有真正的计算函数,可以自己生成甚至不用这个文件,为了实现这个功能则多了一大堆你看了之后想撞墙的代码。但那些代码除了生成FlashBit_BSL_Buffer.dat文件,压根不实用(速度比查表法要慢许多)。
考虑到代码的简洁,上面提供下载的是Simple。如果你想要Professional也不是不可以,我会在稍后贴出来的。下面是这个模块里所有方法、函数的说明:BytesBit_BitsPutToBytes方法
格式:tClass.BytesBit_BitsGetByBytes pBytes(), pBitsLoacte, pBitsValue, pBitsCount[, pHL_Logic][, pBoundLock]
功能:在字符串数组指定位写入指定位长的位值。
参数:byte       pBytes()    被写入的字节数组。
      long       pBitsLoacte 起始位。取值范围(0 To 2^31)。
      long       pBitsCount  写位长。取值范围(-8 to 8)。
                             pBitsCount > 0  从起始位向右读;
                             pBitsCount < 0  从起始位向左读;
                             pBitsCount = 0  无效(不写入)
      Boolean    pHL_Logic   可选参数。位序逻辑。默认为False。
                             =True   书写顺序。
                             =False  逻辑顺序。
      Boolean    pBoundLock  可选参数。字节数组下标锁定。默认为True。
                             =True   不锁定字节数组下标。
                             =False  锁定字节数组下标。
返回:byte       tByte       位值。
说明:1、pBytes()必须是下标从0开始的至少有一个元素的数组,否则会出错。
      2、pBitsLoacte从0开始计数,不能是负值。pBitsLoacte上限可以超出实际字节数组所具备的位数。
      3、pBoundLock=False的情况下,如pBitsLoacte前后位数不足pBitsCount定义的位长,则作如下处理:
         pBitsCount > 0  取从起始位到第0位之间的位长,截取pBitsValue高位写入。
         pBitsCount < 0  取从起始位到第7位之间的位长,截取pBitsValue低位写入。
         pBoundLock=True的情况下,pBitsLoacte后位数不足会扩展字节数组以容纳写入的位。
         但pBitsCount < 0的情况下,如pBitsLoacte前的位数不足则截取pBitsValue低位写入。
      4、pHL_Logic=True  将字节最左边的位作为0位,以符合书写顺序。
         pHL_Logic=False 将字节最右边的位作为0位,以符合逻辑顺序。BytesBit_BitsGetByBytes函数
格式:[tByte] = tClass.BytesBit_BitsGetByBytes(pBytes(), pBitsLoacte, pBitsCount[, pHL_Logic])
功能:从字符串数组指定位读取指定位长的位值。
参数:byte       pBytes()    字节数组。
      long       pBitsLoacte 起始位。取值范围(0 To 2^31)。
      long       pBitsCount  取位长。取值范围(-8 to 8)。
                             pBitsCount > 0  从起始位向右读;
                             pBitsCount < 0  从起始位向左读;
                             pBitsCount = 0  无效(返回0)
      Boolean    pHL_Logic   可选参数。位序逻辑。默认为False。
                             =True   书写顺序。
                             =False  逻辑顺序。
返回:byte       tByte       位值。
说明:1、pBytes()必须是下标从0开始的至少有一个元素的数组,否则会出错。
      2、pBitsLoacte从0开始计数,不能是负值。pBitsLoacte上限可以超出实际字节数组所具备的位数,返回0。
      3、如果pLocate前后位数不足pBitsCount定义的位长,则作如下处理:
         pBitsCount > 0  取从起始位到第0位之间的位,并后后面补足够的0。
         pBitsCount < 0  取从起始位到第7位的位值。
      4、pHL_Logic=True  将字节最左边的位作为0位,以符合书写顺序。
         pHL_Logic=False 将字节最右边的位作为0位,以符合逻辑顺序。BinaryText_SetToBytes函数
格式:[tBytes()] = tClass.BinaryText_SetToBytes(pText[, pLimit])
功能:将八位二进制字符串文本解码为字节数组。
参数:string     pText       八位二进制字符串文本。
      string     pLimit      可选参数。八位二进制字符串之间的分隔符,默认为" "。
返回:byte       tBytes()    字节数组。BinaryText_GetByBytes函数
格式:[tString] = tClass.BinaryText_GetByBytes(pBytes()[, pLimit])
功能:将字节数组编码为八位二进制字符串。
参数:byte       pBytes()    字节数组。
      string     pLimit      可选参数。八位二进制字符串之间的分隔符,默认为" "。
返回:string    tString      八位二进制字符串文本。BinaryString_FormatCheck函数
格式:[tBool] = tClass.BinaryString_FormatCheck(pString)
功能:检测八位二进制字符串的合法性。
参数:string     pString     字节值的八位二进制字符串。
返回:boolean    tBool       True - 合法; False - 非法BinaryString_SetToByte函数
格式:[tByte] = tClass.BinaryString_GetByByte(pString)
功能:从八位二进制字符串取得字节值。
参数:string     pString     字节值的八位二进制字符串。
返回:byte       tByte       字节值。BinaryString_GetByByte函数
格式:[tString] = tClass.BinaryString_GetByByte(pByte)
功能:取字节值的八位二进制字符串。
参数:byte       pByte       字节值。
返回:string    tString      字节值的八位二进制字符串。BinaryBits_Put函数
格式:[tOutByte] = tClass.BinaryBits_Put(pByte, pLocate, pCount, pValue)
功能:将指定长度的位值写入字节指定位置。
参数:byte       pByte       原始字节。
      long       pLocate     起始位。取值范围(7 to 0)。
      long       pCount      写位长。取值范围(-8 to 8)。
                             pCount > 0 从起始位向右写;
                             pCount < 0 从起始位向左写;
                             pCount = 0 无效
      byte       pValue      写位值。
返回:byte       pByte       写值后的字节。
说明:1、这是BinaryBits_MathPut的缓冲版函数。
      2、缓冲函数不对参数值范围做任何检测,取值范围外的参数值会导致程序崩溃。
      3、pLocate对一个字节的8个位序的定义为Bit7,Bit6,Bit5,Bit4,Bit3,Bit2,Bit1,Bit0
      4、如果pLocate前后位数不足pCount定义的位长,则作如下处理:
         pCount > 0  取从起始位到第0位之间的位长,截取pValue高位写入。
         pCount < 0  取从起始位到第7位之间的位长,截取pValue低位写入。
      5、如果pValue的值超过pCount定义的位长,则按pCount定位的位长截取低位。BinaryBits_Get函数
格式:[tOutByte] = tClass.BinaryBits_Get(pByte, pLocate, pCount)
功能:从字节指定位置取指定位长的位值。
参数:byte       pByte       源Byte。
      long       pLocate     起始位。取值范围(7 to 0)。
      long       pCount      取位长。取值范围(-8 to 8)。
                             pCount > 0 从起始位向右取;
                             pCount < 0 从起始位向左取;
                             pCount = 0 无效(返回0)
返回:byte       pByte       位值。
说明:1、这是BinaryBits_MathGet的缓冲版函数。
      2、缓冲函数不对参数值范围做任何检测,取值范围外的参数值会导致程序崩溃。
      3、pLocate对一个字节的8个位序的定义为Bit7,Bit6,Bit5,Bit4,Bit3,Bit2,Bit1,Bit0
      4、如果pLocate前后位数不足pCount定义的位长,则作如下处理:
         pCount > 0  取从起始位到第0位之间的位,并后后面补足够的0。
         pCount < 0  取从起始位到第7位的位值。BinaryBits_Move函数
格式:[tOutByte] = tClass.BinaryBits_Move(pByte, pStep, [pLoop])
功能:对Byte进行算数移位。
参数:byte       pByte       源Byte。
      long       pStep       移位数量。取值范围(-7 to 7)
                             pStep < 0 右移位
                             pStep = 0 不移位
                             pStep > 0 左移位
      boolean    pLoop       循环移位开关。取值范围(0,1)默认为0。
                             pLoop = 0 不循环
                             pLoop = 1 循环
返回:byte       tOutByte    移位后的Byte。
说明:1、这是BinaryBits_MathMove的缓冲版函数。
      2、缓冲函数不对参数值范围做任何检测,取值范围外的参数值会导致程序崩溃。

解决方案 »

  1.   

    拉登可能用了个比较简单的方法~~如
    COPY 1.jpg /B + 1.txt /A 2.jpg用记事本2.jpg打开到最后可以看到文本的内容
    ^_^
      

  2.   

    SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
      

  3.   

    I am sorry .
    I am hurry!
      

  4.   

    拉登可能用了个比较简单的方法~~ 如 
    COPY 1.jpg /B + 1.txt /A 2.jpg 用记事本2.jpg打开到最后可以看到文本的内容 
      

  5.   

    查表法虽然直观,但是对 Byte 这种无符号整数,直接运算更快。
    表的大小勉强算得上变态。§函数
    'Byte 类型的移位操作
    '2008-08-04, Tiger_Zhao
    Option Explicit'左移
    Function LShift(ByVal Value As Byte, ByVal bits As Long) As Byte
        Dim byTopBit        As Byte
        Dim i               As Long
        
        If Value = 0 Then Exit Function
        
        Select Case bits
            Case 0:     LShift = Value
            Case 1:     LShift = (Value And &H7F) * &H2
            Case 2:     LShift = (Value And &H3F) * &H4
            Case 3:     LShift = (Value And &H1F) * &H8
            Case 4:     LShift = (Value And &HF) * &H10
            Case 5:     LShift = (Value And &H7) * &H20
            Case 6:     LShift = (Value And &H3) * &H40
            Case 7:     LShift = (Value And &H1) * &H80
        End Select
    End Function'循环左移
    Function LShiftZ(ByVal Value As Byte, ByVal bits As Long) As Byte
        If Value = 0 Then Exit Function
        
        If bits = 0 Then
            LShiftZ = Value
        Else
            LShiftZ = LShift(Value, bits) Or RShift(Value, 8 - bits)
        End If
    End Function'右移
    Function RShift(ByVal Value As Byte, ByVal bits As Long) As Byte
        Dim byTopBit        As Byte
        Dim i               As Long
        
        If Value = 0 Then Exit Function
        
        Select Case bits
            Case 0:     RShift = Value
            Case 1:     RShift = Value \ &H2
            Case 2:     RShift = Value \ &H4
            Case 3:     RShift = Value \ &H8
            Case 4:     RShift = Value \ &H10
            Case 5:     RShift = Value \ &H20
            Case 6:     RShift = Value \ &H40
            Case 7:     RShift = Value \ &H80
        End Select
    End Function'循环右移
    Function RShiftZ(ByVal Value As Byte, ByVal bits As Long) As Byte
        If Value = 0 Then Exit Function
        
        If bits = 0 Then
            RShiftZ = Value
        Else
            RShiftZ = RShift(Value, bits) Or LShift(Value, 8 - bits)
        End If
    End Function
    §调用方式
    (1) BinaryBits_Move(): pStep = [0..7], pLoop = 0
    (2) LShift(): pStep 同上
    (3) BinaryBits_Move(): pStep = [-7..7], pLoop = 1
    (4) : pStep 同上
        If pStep < 0 Then
            n = RShiftZ(pByte, Abs(pStep))
        Else
            n = LShift(pByte, pStep)
        End If§运行方式
    (A) 在 IDE 中执行
    (B) 不选任何优化选项,编译成 exe 执行
    (C) 选择全部优化选项,编译成 exe 执行§测试结果
    --- ----- ----- ----- -----
         (1)   (2)   (3)   (4)
    --- ----- ----- ----- -----
    (A) 3.204 2.393 5.446 8.189
    (B) 0.641 0.158 1.200 0.398
    (C) 0.605 0.080 1.133 0.311
    --- ----- ----- ----- -----
      

  6.   

    稍微更正一下,调用方式(4)用的是 LShiftZ 而不是 LShift
      

  7.   

    VB不能移位,用C++呀...非得要用VB吗?
      

  8.   


    非常感谢老鸟的赐教。刚刚做了测试,发现了一些现象:FlashBit是以一个Class模块提供的。其实它没必要非写成Class模块。
    在这种状态下:LShiftZ 0.58秒、BinaryBits_Move是1.5秒。把FlashBit改成一般的模块。无论pBit是正值还是负值、是否循环,测试结果均是:
    LShiftZ 0.56秒、BinaryBits_Move是0.76秒。
    BinaryBits_Move函数本身不是一个函数,而是一个叫priBuffer_BinaryBits_Move()的表。
    这个表涵盖了左右、循环操作,因此不大可能有速度上的差别。就单独移位操作而言,LShiftZ确实最快。实际也多次发现查表缓冲不如直接计算快的情况。但对于更复杂的BinaryBits_Get和BinaryBits_Put函数。他们也是同样结构的查表函数,速度几乎和BinaryBits_Move一样快。
      

  9.   


    的确是用函数或类封装数组后性能急剧下降,下面是单纯对数组的访问测试,特别是优化编译后,与直接访问数组的差别不止一个数量级。§运行方式
    (A) 在 IDE 中执行
    (B) 不选任何优化选项,编译成 exe 执行
    (C) 选择全部优化选项,编译成 exe 执行§测试结果
    ---------------- ------ ------ ------
        调用方式       (A)    (B)    (C) 
    ---------------- ------ ------ ------
    全局静态数组      3.306  1.284  0.060
    全局动态数组      3.242  0.817  0.058
    局部静态数组      5.193  1.294  0.060
    局部动态数组      5.479  0.854  0.057
    函数封装静态数组 14.065  1.489  1.317
    函数封装动态数组 14.089  1.154  0.904
    对象封装静态数组 28.090  5.361  5.424
    对象封装动态数组 28.434  5.372  5.477
    ---------------- ------ ------ ------
      

  10.   

    将 priBuffer_BinaryBits_Move 复制到模块中直接访问,查表法的速度优势才算体现出来了。
    值得引以为戒,由于结构设计的原因影响了性能。§调用方式
    (1) (Object)BinaryBits_Move(): pStep = [0..7], pLoop = 0
    (2) (Module)BinaryBits_Move(): pStep = [0..7], pLoop = 0
    (3) LShift(): pStep 同上
    (4) (Object)BinaryBits_Move(): pStep = [-7..7], pLoop = 1
    (5) (Module)BinaryBits_Move(): pStep = [-7..7], pLoop = 1
    (6) : pStep 同上
        If pStep < 0 Then
            n = RShiftZ(pByte, Abs(pStep))
        Else
            n = LShiftZ(pByte, pStep)
        End If§运行方式
    (A) 在 IDE 中执行
    (B) 不选任何优化选项,编译成 exe 执行
    (C) 选择全部优化选项,编译成 exe 执行§测试结果
    --- ------ ------ ------
          (A)    (B)    (C) 
    --- ------ ------ ------
    (1)  3.153  0.689  0.609
    (2)  0.371  0.027  0.006
    (3)  2.301  0.143  0.077
    (4)  3.121  0.674  0.601
    (5)  0.350  0.026  0.006
    (6) 11.602  0.515  0.448
    --- ------ ------ ------
      

  11.   

    我也写过,是为用md5加密word文档,不过单独测试什么输入都没问题,但是放算法里第二次循环就溢出了
      

  12.   

    写它的动机来自于以VB编写哈夫曼编码/解码器和单片机应用的一些需求……………………………………(将近9MB大的一个表,非常变态)。 --------------------------------------------单片机的ROM可是非常有限啊,通常都是以K计的,9M的表,太夸张了吧!
    鲜美,你又顽皮了。
      

  13.   

    左移右移不是可以用 >>  和  <<  吗?比如 
             Dim test As Byte = 64
            MsgBox(test >> 2)
      

  14.   

    果然变态 + 很久不见小仙妹 = 狂顶此帖关于类似这种问题,我的另一个变态解决方案是用VC写一个DLL提供所需的功能函数。然后把DLL作为VB的资源文件整合到单一EXE文件中。用的时候把DLL释放到临时目录中然后调用。这样一直干得好好的,可是不知从什么时候开始,杀毒软件不让从临时文件目录调用可执行代码了,弄得我很头疼。所以说,还是小仙妹更加变态哦!
      

  15.   

    KiteGirl(小仙妹):
    好妹妹,你真棒!你的FlashBit真的很不错!
    我真的很受启发,也很受用!
    谢谢!如果有机会一定很想认识一下你!
    向你致敬!!!
      

  16.   

    VC写个DLL导出函数,用VB调用,比你的可靠强壮多少倍。
      

  17.   

    【VB下实现对Bit操作的一组实用函数】
    占位学习!